From 75d4a30c1fefcc64a2b90183e42feeb8c59cbdd2 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Fri, 10 Aug 2018 16:51:32 +0300 Subject: [PATCH] Update dependencies and replace uuid library (#100) --- Gopkg.lock | 228 +- Gopkg.toml | 4 - acmetxt.go | 6 +- api_test.go | 4 +- db.go | 2 +- types.go | 5 +- validation.go | 6 +- validation_test.go | 5 +- .../github.com/gavv/httpexpect/.gometalinter | 4 +- vendor/github.com/gavv/httpexpect/.travis.yml | 3 +- .../github.com/gavv/httpexpect/value_test.go | 201 + vendor/github.com/google/uuid/.travis.yml | 9 + vendor/github.com/google/uuid/CONTRIBUTING.md | 10 + vendor/github.com/google/uuid/CONTRIBUTORS | 9 + .../{klauspost/crc32 => google/uuid}/LICENSE | 3 +- vendor/github.com/google/uuid/README.md | 23 + vendor/github.com/google/uuid/dce.go | 80 + vendor/github.com/google/uuid/doc.go | 12 + vendor/github.com/google/uuid/hash.go | 53 + vendor/github.com/google/uuid/json_test.go | 62 + vendor/github.com/google/uuid/marshal.go | 39 + vendor/github.com/google/uuid/node.go | 103 + vendor/github.com/google/uuid/seq_test.go | 66 + vendor/github.com/google/uuid/sql.go | 58 + vendor/github.com/google/uuid/sql_test.go | 102 + vendor/github.com/google/uuid/time.go | 123 + vendor/github.com/google/uuid/util.go | 43 + vendor/github.com/google/uuid/uuid.go | 191 + vendor/github.com/google/uuid/uuid_test.go | 526 + vendor/github.com/google/uuid/version1.go | 44 + vendor/github.com/google/uuid/version4.go | 38 + .../klauspost/compress/.gitattributes | 1 + .../github.com/klauspost/compress/.travis.yml | 51 +- .../github.com/klauspost/compress/README.md | 242 +- .../klauspost/compress/compressible.go | 63 + .../klauspost/compress/compressible_test.go | 121 + .../klauspost/compress/flate/inflate.go | 108 +- .../klauspost/compress/flate/reader_test.go | 11 +- .../klauspost/compress/fse/README.md | 79 + .../klauspost/compress/fse/bitreader.go | 107 + .../klauspost/compress/fse/bitwriter.go | 168 + .../klauspost/compress/fse/bytereader.go | 56 + .../klauspost/compress/fse/compress.go | 684 + .../klauspost/compress/fse/decompress.go | 370 + .../github.com/klauspost/compress/fse/fse.go | 138 + .../klauspost/compress/fse/fse_test.go | 310 + .../001e59af3c698337b5449d856ef447fd0c0b47ff | Bin 0 -> 10001 bytes ...00f14dd34076a71e9e54b9b88497c2a214c91d81-3 | 1 + ...01a027e4ad99a383228779f2aaf1a2f4a3f3857b-3 | 1 + ...028b20cc463cb40889c44f46b67d13db0c6b50a2-2 | 1 + ...2a4a6eccf33f032b9acc928be2f5377b31d0b03-11 | 1 + ...03648029374f39fc083b90d39df1f80ecc1fa78e-1 | 1 + ...067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 | 1 + ...b0a852a4680d8f3fe07ad0e9997b18186918c78-10 | 1 + ...0c33deff4510591c4ec94593a4d13f9d899523e4-5 | 1 + ...0c851d4e4c8b5055b6ce3b68089892203057b3c0-4 | 1 + .../0d0de3f34f3d27f32d12be358cb2dde550d72172 | Bin 0 -> 63 bytes ...0ead65857937e78706dcaf139c616ef71533b94d-2 | 1 + ...110c8a30c16070bf2813480d9492a1a170a7d80a-4 | 1 + ...138deac60e8494cd0329602411774ea9ba629f72-6 | 1 + ...19aa2a437fa2a48199cc0294469a0a942ae1483a-4 | 1 + ...1b6cc66a7d78b5b1f37a7d4d7efaaeed1a6ce630-9 | 1 + .../1bf17f213e2aee50a14d920aa1c615edab1b4d11 | 1 + ...1cfd49b23106a3de30052a18cee3bed23d08f552-7 | 1 + ...1ecd000fbf02c3bd4cf7cfa7a314580789536ab0-3 | 1 + ...f2a2c8867dce3ed56fef849e5de664c20cdae39-10 | 1 + ...1f969240d093a413365023cc05432790a500046a-1 | Bin 0 -> 52 bytes ...1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 | 1 + ...2547cc736e951fa4919853c43ae890861a3b3264-4 | Bin 0 -> 3 bytes ...254bff7e4526a1c06684242ce8c6f32b07466192-2 | 1 + ...26157894111c075cd978a0a67a1bd2c6184e92d6-3 | Bin 0 -> 33 bytes .../26cc3dcead75312b7037f0c81d2a88ea04cf2c48 | Bin 0 -> 1064 bytes ...283e76a3a5ac43d02ad685c555a6eb9a8fbe88e5-4 | 1 + ...84e42ad2dbdfcfb6c7e6c7d5ad1bcc7e911f96f-10 | 1 + ...2891dddca25448c8f1671b9779f715b45e6ebef0-3 | 1 + ...2b8284f1553bb6e799466377047fff8a30e1dba0-6 | 1 + ...c3a94ad7435a7c8ae24df733e7c3a1044b38580-10 | 1 + .../326998db244ec22e4545688efc3fcf761edcfa47 | Bin 0 -> 62 bytes ...32796a5dc0d50e6c16a3400af331c4a1788d2620-4 | 1 + ...33844260640d4b3bc276376be9b5b5a1c53350cb-8 | Bin 0 -> 12 bytes ...33d53df606943afe544548920b1b8bd3e1ecf731-7 | 1 + ...3473974824e5391343390e25b1e250edf2ab45cf-6 | Bin 0 -> 5 bytes ...393fe96068641f74607dd7eebde0807de355944a-2 | 1 + ...3ac84d808844f1204e0704eb2d87a083d17e5edf-4 | Bin 0 -> 29 bytes ...3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 | 1 + ...3ca5ae6d9b3a1d465c8214e272c32a60ebc0c848-2 | 1 + .../3d648fdd4eee536b735033f7eb135b28ca5c8526 | 1 + ...3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 | Bin 0 -> 8 bytes .../3e9b93aed9d65aab72e65351b433bce4a091ab0d | Bin 0 -> 583 bytes ...fc41ed16660ff04dc86763d24f7f41e7ac72e57-10 | 1 + ...40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 | 1 + .../440ac3e84eb89ba7c864261c36567ec92f111be5 | 1 + ...44a33b09be4119510e06b8cf5f695658dd0da430-3 | 1 + ...463d78c147df54fb78e55f52f79c9dff7a42c5c3-4 | 1 + ...4a076c6a1ff5c3956d52a9a18c90636d9271d5dc-8 | 1 + .../4a0e9c56d9b4d655b8c750e01b63aaee512c79dd | 1 + ...4c2d1f5dfeb5273fe3c44edc2c9b016159d23b5c-3 | 1 + ...4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 | 1 + .../4f480dad3c4e936864adaa7707bac06e59272d96 | Bin 0 -> 307 bytes ...4f784804ea2ba40c6ff5251b1c092c382b8ff236-3 | Bin 0 -> 12 bytes ...500ce5edbda324f9a385f06a24094cee873bcf07-6 | Bin 0 -> 6 bytes ...5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 | Bin 0 -> 5 bytes ...537d5d54bfa6fbdce3e0d7b7746097ba124ee7d8-3 | 1 + ...54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 | 1 + ...55a0c930a804665fd0ae2aa914e39ec2898babaf-7 | Bin 0 -> 7 bytes .../56032dcc54f0d2fa736dd71962caa4e3e240abf0 | 1 + .../576280c2b993d7a52ac7c741273336f8bd9213f5 | 1 + .../59d26deac1ea4b1ad0e2d65b20839f7d2d4a4b89 | Bin 0 -> 186 bytes ...5b4999d4bd9c1b77f6004595bc2e80bf6c7180af-4 | 1 + ...5bf1f7b62d3967f98c64b19a4b2c0d61b70e6222-2 | Bin 0 -> 89 bytes ...6548f73fac595761f3cf335b35d1ff524d67f09f-5 | Bin 0 -> 32 bytes ...68d516dd85ef75af6a2cd31394eebab11b024fe4-3 | 1 + ...69c449d595dc232b2ad88b0b48395948a23a0650-2 | 1 + ...6afbd7493a57d48d401da68efdc79156ccc1992c-1 | 1 + .../6b50366cad8565e61d162e38cf031c918d305dd3 | Bin 0 -> 127 bytes .../6b93512fc409ba81e69a6c818c47540e47dcb9a4 | Bin 0 -> 1817 bytes .../6b99950532c007f8f24725686d8142ddf390889b | Bin 0 -> 1303 bytes ...6d9dd11e564c301aa0a6043ee59e00c9b0192334-8 | 1 + ...6e53664c27b28370ee8680e4e4dfd139b43c2850-2 | 1 + ...6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 | Bin 0 -> 5 bytes ...6ee6aab4898dc237d1504802293ff1e36e07d7d7-2 | 1 + ...6eea60261259d0ed848b459866a9a7ccebf25f02-4 | Bin 0 -> 45 bytes .../70dcd94d449aa197672f8cabcc88a21254131687 | 1 + .../72677d19506938afc885d16fd5ca7c4be75f3752 | 1 + ...732e566ac977d41409549e42c4b6ff6b0913b3cc-2 | 1 + .../747d7c993787ae22ace6ec322dc1f098c938ec1f | Bin 0 -> 7182 bytes ...75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 | Bin 0 -> 6 bytes ...764ca341b24c6a68ad9507a31abcc33287f6c994-1 | 1 + ...7b56b7ac07966b8060919498d93a47e68730d20a-2 | 1 + ...7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 | Bin 0 -> 93 bytes .../7d2570a230d731b54e04320f4bce5693d5bd4176 | Bin 0 -> 9828 bytes ...84859b8196cb65505cda9c056cbecb4096fd4879-7 | 1 + ...889fdb56e3b7b79e51e66ed1c47fb0b60970d054-2 | 1 + .../8c562007589132e496325ea892733466e03a06cb | Bin 0 -> 768 bytes .../8e78a58162034efce763c158087c6f1e427c1260 | 1 + ...150349979ceed8b2f6db6e0ed836462cd27d499-1} | 2 +- ...91a9bc8bbcab0dc05bedaf5f4aa8d383c1651fb2-5 | Bin 0 -> 60 bytes ...9278d66afee65127b44cdd505e55580e1faa2377-1 | Bin 0 -> 8193 bytes .../9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b | Bin 0 -> 837 bytes ...9355e3410f2f344ecd5dd798819020a35461c2df-2 | 1 + ...9544d0384139d241f81c841cb63f4a6bf2c3d55e-4 | Bin 0 -> 33 bytes .../9802e09660b74c259960141c89402b5fdececf3f | Bin 0 -> 55 bytes ...98840eab4f9516cedcdcc88302b3639672a42f06-2 | 1 + ...9a71d9b48c814eb1b0db3133482c06a079de2bc8-4 | 1 + ...9a86f34bfd765bab80845da7128ab574d6abdef1-5 | 1 + .../9cd2374f626d4c55ce9389368b428a74be518319 | 1 + ...9d52d6b15a5ee8cd7a575bac4dec1025573ad062-2 | 1 + .../9e6953ce446955eed1bee2d9819461068d2d37f6 | 1 + ...a0704a231fa435579a323a222d91a03fe3b5cbc2-6 | Bin 0 -> 53 bytes ...a1f084b3911d33e6b41f2ba29efbf9140800444e-3 | 1 + ...a3953bd6a594600ab51268955ecee6fea8be4709-8 | Bin 0 -> 8 bytes ...a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 | 1 + ...a8e6fe772a578fe63546761ea1c195ff61203810-4 | Bin 0 -> 13 bytes ...aed10bc423e56534538d83702d4be2aa281549a9-4 | 1 + ...b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 | Bin 0 -> 89 bytes ...b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 | 1 + .../b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 | Bin 0 -> 42 bytes ...b22334c4d7507820a3b901dcba18b20a74b28f22-7 | Bin 0 -> 6 bytes ...b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 | 1 + .../b60c99af5868c013f98cdce9781b4fffeed81f30 | 1 + ...b62b1d73848fde9b74a166239cef1a76506a9e41-1 | 1 + ...b7b180de011becb75b415d308134a35b1c3e075f-1 | 1 + ...bdd90d98c50056c82fa01cdee2d91ef30112c4d7-1 | 1 + ...c0a4a69dff77a11d744507864de0a15d000afd3f-5 | 1 + ...c372591e0c943653714cdc9b1e52f6b0a49a0ab6-3 | Bin 0 -> 32 bytes .../c3d814235d50a4f96ced41bf5fc9c53c4e408765 | Bin 0 -> 78 bytes .../c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 | Bin 0 -> 52 bytes .../c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d | Bin 0 -> 90 bytes .../c775292f392c027f7d24e5a1c84b1dd176c03f32 | 1 + ...ca269332cbd02cb17415e5cfc4ef7403875ef755-5 | 1 + .../cedd771f15bd51b21b91d2535588e6bfd943456e | Bin 0 -> 16658 bytes ...d22b7d7f10d50e7cd68cfb65ac60ce2af5e05f0a-5 | Bin 0 -> 12 bytes ...d24d432b5104847324add3b047f71cfbb2cf11a2-5 | 1 + ...d2a3b921d428c6ef1dc976623d0fd3914b8b5924-7 | 1 + ...d5c5747ded386a1de2be97f8fa56f27dbf866331-3 | 1 + ...68e96f1fdefcc1ca114970b7d9ef1cbd5a0cc50-10 | 1 + ...d9af7dc7888daf056627088aef8cfadd5817660c-6 | Bin 0 -> 7 bytes .../da39a3ee5e6b4b0d3255bfef95601890afd80709 | 0 ...dbada9d56b10891ca136d80794bb93ad9e58293a-7 | Bin 0 -> 10 bytes ...de357612a902159ac2a91a9cd6b0d7287d55e968-6 | 1 + ...de7d905f4388e2955b0a11f42517882f0ff5792b-2 | 1 + ...decd27d54bcedc965463c545a051f44c140cfb6b-3 | Bin 0 -> 5 bytes ...e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 | 1 + ...e3b22b4eb898b68dde1c73dab4629c38025031db-5 | 1 + .../e55f990e122023ab58626ef27e06422b7c4be053 | Bin 0 -> 260 bytes .../e77d34eb148eb0a3b30feffc7e9b56cd182dc74c | 1 + ...ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 | Bin 0 -> 8 bytes ...f52fb64e8823fdebdb11ae1c231358fcce57e638-6 | 1 + ...f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 | Bin 0 -> 262 bytes ...f748f012d8d9bd2b168aa96c529658761dd648a4-1 | 1 + ...f8f96538c274d717ccca38324c9aa658e67180dd-1 | Bin 0 -> 128 bytes .../fad75398a55edd191340909bf867610b6bc72ff7 | Bin 0 -> 248 bytes ...fb51f26fe62e769ba34f569454121f46f2a4d277-8 | 1 + .../fca6bc86ec8711a1e7745c03237087d55d936a67 | 1 + ...fd155cfb10f96df4544263f5d2164351ae97f806-4 | Bin 0 -> 44 bytes ...fe5567e8d769550852182cdf69d74bb16dff8e29-1 | 1 + .../001e59af3c698337b5449d856ef447fd0c0b47ff | Bin 0 -> 4211 bytes ...03648029374f39fc083b90d39df1f80ecc1fa78e-1 | Bin 0 -> 56 bytes ...057294475853d7ff15d86d889f592eb7ba6b2e72-8 | Bin 0 -> 4 bytes ...067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 | Bin 0 -> 171 bytes ...0c33deff4510591c4ec94593a4d13f9d899523e4-5 | 1 + ...0d67d398462565f4d9e21f5efe9b0a6816e8962c-3 | Bin 0 -> 49 bytes ...0ead65857937e78706dcaf139c616ef71533b94d-2 | Bin 0 -> 169 bytes ...19aa2a437fa2a48199cc0294469a0a942ae1483a-4 | 1 + .../1bf17f213e2aee50a14d920aa1c615edab1b4d11 | Bin 0 -> 59 bytes ...1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 | 1 + ...26157894111c075cd978a0a67a1bd2c6184e92d6-3 | Bin 0 -> 32 bytes .../26cc3dcead75312b7037f0c81d2a88ea04cf2c48 | Bin 0 -> 554 bytes ...1a1eb16673086976295a4042ccef7fa443503df-11 | Bin 0 -> 5 bytes .../326998db244ec22e4545688efc3fcf761edcfa47 | Bin 0 -> 58 bytes ...32796a5dc0d50e6c16a3400af331c4a1788d2620-4 | 1 + ...27ed0588eb0b927e81d9b9adfd8aa98a1a5081d-10 | 1 + ...33844260640d4b3bc276376be9b5b5a1c53350cb-8 | 1 + ...3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 | 1 + .../3d648fdd4eee536b735033f7eb135b28ca5c8526 | Bin 0 -> 127 bytes ...3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 | 1 + .../3e9b93aed9d65aab72e65351b433bce4a091ab0d | Bin 0 -> 372 bytes ...40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 | 1 + .../440ac3e84eb89ba7c864261c36567ec92f111be5 | 1 + .../4a0e9c56d9b4d655b8c750e01b63aaee512c79dd | 1 + ...4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 | 1 + .../4f480dad3c4e936864adaa7707bac06e59272d96 | Bin 0 -> 226 bytes ...500ce5edbda324f9a385f06a24094cee873bcf07-6 | 1 + ...5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 | 1 + ...545816fc75823315f58483bdc08de39b4b26f487-6 | 1 + ...54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 | 1 + ...555d303800fd439e509e0720e6d7cf04f744ec2f-2 | 1 + ...55a0c930a804665fd0ae2aa914e39ec2898babaf-7 | 1 + .../56032dcc54f0d2fa736dd71962caa4e3e240abf0 | Bin 0 -> 1003 bytes ...566fbce2e12fd9efdb9165b796da786e66bf036c-9 | 1 + .../576280c2b993d7a52ac7c741273336f8bd9213f5 | Bin 0 -> 438 bytes ...577c882a297cbdf4233695231e12accbcc2abdcd-4 | 1 + .../59d26deac1ea4b1ad0e2d65b20839f7d2d4a4b89 | Bin 0 -> 178 bytes ...5bf1f7b62d3967f98c64b19a4b2c0d61b70e6222-2 | Bin 0 -> 62 bytes ...5c795ad342ff2a0f69ada3f3382ba05013387264-8 | 1 + .../64426d08b2cefc746ec73d04daae35a27dd53ccf | 1 + ...6548f73fac595761f3cf335b35d1ff524d67f09f-5 | Bin 0 -> 30 bytes ...68d516dd85ef75af6a2cd31394eebab11b024fe4-3 | 1 + ...69c449d595dc232b2ad88b0b48395948a23a0650-2 | 1 + .../6b50366cad8565e61d162e38cf031c918d305dd3 | Bin 0 -> 122 bytes .../6b93512fc409ba81e69a6c818c47540e47dcb9a4 | Bin 0 -> 962 bytes .../6b99950532c007f8f24725686d8142ddf390889b | Bin 0 -> 767 bytes ...6ce2e7227237a64b8bc0b5c27f018bfd2a2227f2-5 | 1 + ...6e53664c27b28370ee8680e4e4dfd139b43c2850-2 | 2 + ...6eb5eee33ab96304ffc66043a961108878b0565f-9 | 1 + ...6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 | 1 + .../72677d19506938afc885d16fd5ca7c4be75f3752 | Bin 0 -> 5803 bytes .../747d7c993787ae22ace6ec322dc1f098c938ec1f | Bin 0 -> 2998 bytes ...75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 | 1 + ...764ca341b24c6a68ad9507a31abcc33287f6c994-1 | 1 + ...7b56b7ac07966b8060919498d93a47e68730d20a-2 | Bin 0 -> 123 bytes ...7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 | 1 + .../8c562007589132e496325ea892733466e03a06cb | Bin 0 -> 502 bytes .../8e78a58162034efce763c158087c6f1e427c1260 | Bin 0 -> 94 bytes ...9278d66afee65127b44cdd505e55580e1faa2377-1 | Bin 0 -> 3442 bytes .../9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b | Bin 0 -> 466 bytes .../9802e09660b74c259960141c89402b5fdececf3f | Bin 0 -> 46 bytes ...98840eab4f9516cedcdcc88302b3639672a42f06-2 | 1 + ...a3d36ff249d8734de00dcaec41bcbf160adaecf-10 | Bin 0 -> 5 bytes .../9cd2374f626d4c55ce9389368b428a74be518319 | Bin 0 -> 235 bytes .../9e6953ce446955eed1bee2d9819461068d2d37f6 | 1 + ...a3953bd6a594600ab51268955ecee6fea8be4709-8 | 1 + ...a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 | 1 + ...ae1137dce39774d2ba19b77b1fc915c57ba95523-3 | 1 + ...b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 | 1 + ...b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 | 1 + .../b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 | 1 + ...b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 | 2 + .../b60c99af5868c013f98cdce9781b4fffeed81f30 | Bin 0 -> 1968 bytes ...b62b1d73848fde9b74a166239cef1a76506a9e41-1 | Bin 0 -> 1097 bytes ...bedb6456c65af2ca319c6630db22f2e362dd73f2-5 | 1 + ...c0a4a69dff77a11d744507864de0a15d000afd3f-5 | 1 + ...c2d596d0601332a809c19c0347580c78b079f822-8 | 1 + .../c3d814235d50a4f96ced41bf5fc9c53c4e408765 | 1 + .../c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 | 1 + .../c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d | 1 + .../c775292f392c027f7d24e5a1c84b1dd176c03f32 | Bin 0 -> 29 bytes .../cedd771f15bd51b21b91d2535588e6bfd943456e | Bin 0 -> 6751 bytes ...da39a3ee5e6b4b0d3255bfef95601890afd80709-9 | 0 ...da3ec0c217bfb46b23a5044192571ae8eb5bd2b7-9 | Bin 0 -> 4 bytes ...dbada9d56b10891ca136d80794bb93ad9e58293a-7 | 1 + ...de0ea11f2f9d6c773542b53337f688d655918f76-7 | 1 + ...de15b9702bd007145d26f7b5ddea83a93ecee381-5 | Bin 0 -> 9 bytes ...de357612a902159ac2a91a9cd6b0d7287d55e968-6 | 1 + ...decd27d54bcedc965463c545a051f44c140cfb6b-3 | 1 + ...e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 | 1 + ...e395861f9b34c58744c48a34a0d471241957cec5-2 | Bin 0 -> 26 bytes .../e55f990e122023ab58626ef27e06422b7c4be053 | Bin 0 -> 242 bytes .../e77d34eb148eb0a3b30feffc7e9b56cd182dc74c | Bin 0 -> 174 bytes ...c8f2472897dd80c1c5f5c958c665d18a8602e55-10 | Bin 0 -> 4 bytes ...ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 | 1 + ...f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 | Bin 0 -> 250 bytes ...f748f012d8d9bd2b168aa96c529658761dd648a4-1 | Bin 0 -> 202 bytes ...f8f96538c274d717ccca38324c9aa658e67180dd-1 | Bin 0 -> 123 bytes .../fad75398a55edd191340909bf867610b6bc72ff7 | Bin 0 -> 231 bytes .../fca6bc86ec8711a1e7745c03237087d55d936a67 | 2 + ...fd155cfb10f96df4544263f5d2164351ae97f806-4 | Bin 0 -> 38 bytes ...fdd2a48761f050f1f83fa279882eee5c8378f9d9-3 | Bin 0 -> 49 bytes .../compress/fse/fuzz/run-compress.cmd | 4 + .../compress/fse/fuzz/run-decompress.cmd | 4 + .../klauspost/compress/fse/fuzz_compress.go | 25 + .../klauspost/compress/fse/fuzz_decompress.go | 19 + .../klauspost/compress/fse/highbit_go19.go | 9 + .../klauspost/compress/fse/highbit_old.go | 18 + .../klauspost/compress/gzip/example_test.go | 2 +- .../klauspost/compress/gzip/gunzip.go | 2 +- .../klauspost/compress/gzip/gunzip_test.go | 34 + .../klauspost/compress/gzip/gzip.go | 2 +- .../klauspost/compress/huff0/.gitignore | 1 + .../klauspost/compress/huff0/bitreader.go | 115 + .../klauspost/compress/huff0/bitwriter.go | 176 + .../klauspost/compress/huff0/bytereader.go | 54 + .../klauspost/compress/huff0/compress.go | 600 + .../klauspost/compress/huff0/compress_test.go | 437 + .../klauspost/compress/huff0/decompress.go | 392 + .../compress/huff0/decompress_test.go | 482 + ...01ace8efdfd46d82b0fef511b259933ced9d13ec-2 | 1 + ...049f4a878ab48c404bd0950e2366e3c0eaad4318-3 | Bin 0 -> 41 bytes ...04bc4648208f40ba61ffb9a929f760c24101522c-1 | Bin 0 -> 1647 bytes .../0a7ce59229caf93ee64d5a828aecab7b5e434bbc | 1 + .../0ceda9053c751bf974334c7c1676832feea92d69 | Bin 0 -> 1919 bytes ...0dde84d337ceb9269489c3919d205ea9789c158a-5 | 1 + ...0e90b9893889f69194ca72e28082a1f6081c4b35-1 | 1 + ...0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 | Bin 0 -> 117 bytes ...112b9d35e8cbeabce6fda543aec804ab83185543-1 | 1 + ...130efc33e0d8f0327a73110deac85474bc91dc8d-3 | Bin 0 -> 4 bytes .../1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 | 1 + .../234ec5ad1fc105fcc08523ff91bd8430284aa1f3 | Bin 0 -> 131073 bytes ...26ccc59f9c4d89063210f2e8ddd0c26394c2a607-2 | 1 + .../287d18afe5e0d54d4554a39aa2acff99d696136d | 1 + ...29e95908e0f3e9f3e189441de6ed797b7bee2449-2 | 1 + ...c93d4381a547aa7001acfffcf51dc323a0cdf2b-10 | Bin 0 -> 67 bytes ...2e0d10ca05bdebe3fe84c481004adb11a1cc761c-2 | Bin 0 -> 1700 bytes ...2e85ccbaa127cbf77bb8f0b5c3afdcf53f63f2d8-2 | 1 + .../30632e96a06600a75b47b4cbe0db74b959d09aa5 | Bin 0 -> 553 bytes ...08f53f64ce26d56e4379931ff3611a7dd49325f-10 | Bin 0 -> 64 bytes ...31e020e2f79260ddcbf377c8e1256288b57d32b8-1 | 1 + ...32a3cf4aef238d77278831c3744c1327dcc8f8c0-3 | Bin 0 -> 3 bytes ...350b061ff78cfb97b28716ec96e27f616d439f97-1 | Bin 0 -> 302 bytes ...3542214eb977ea9bdabcc55601d7876b6227b501-2 | Bin 0 -> 506 bytes ...3693a58b98ececb7670844f49caa795c1735ddf0-1 | Bin 0 -> 292 bytes ...3b1d88a86a30b301e5f509a756f43ef34fad55b0-2 | Bin 0 -> 1055 bytes ...f85a2df398429128e89cb13f51f612645550408-11 | Bin 0 -> 16 bytes .../40b8de701a171fddefdc4459023121a1e605b16c | 1 + ...4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 | Bin 0 -> 1089 bytes .../43726b29460c5060782f19cb0facac8443ad5d0b | 2 + .../43a26357597ae65521480220432ff645450d01f1 | Bin 0 -> 1476 bytes ...46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 | 1 + .../4869e00fbc61867ccab5b83187c3a146ecb36775 | Bin 0 -> 982 bytes .../489d689da4860f3116a62db6b089bb0d5ba4de40 | Bin 0 -> 2569 bytes ...48bc76aeb21bc6070323247927d87e591e51eaa9-1 | Bin 0 -> 984 bytes ...4959a4a9db83af17f9368cf490b8a0356d872147-1 | Bin 0 -> 298 bytes ...49dce428e704656d5a4f1053a443ba44f51e91f0-4 | Bin 0 -> 4 bytes ...4a98d52bab6ca703e4521093afa2a400e10f4a7d-2 | Bin 0 -> 342 bytes ...4b4859f278820e969c13c975669322e2c9df9823-5 | Bin 0 -> 6 bytes ...4d1adbc376464b88c52a00ed562cdacbffa4af1a-1 | Bin 0 -> 166 bytes ...4f506d462241876610a0f92a5aa1e2b38ea8722c-7 | Bin 0 -> 10 bytes ...51bdcd2cbd098b042fddc528083572bdbcfbe449-1 | Bin 0 -> 346 bytes ...51c91bfe65eaa40fe4144306d6332ad84e4bb8ed-1 | 1 + ...53bcc0e78275d3efe9e012e6d30412066bf354f9-2 | 1 + ...545828581071b0d01c3fd9d15c7850c3f83ea15f-2 | Bin 0 -> 25 bytes ...56860900c11ef30e85ce99b14e0e687745b269ae-9 | Bin 0 -> 63 bytes ...581ed2fb7f25a6a5a8de40beae3dfd1666c511d0-2 | 1 + .../5b5d4262260375deb5146e3fa43f689923e856a7 | Bin 0 -> 5895 bytes ...5c4b6679ee378f2533b099450ed21e40d54f6cd0-3 | 1 + ...5e13404b6713db5f2d4972747da143057beaaf64-2 | 1 + ...5e6c62abd0fe49668d26e9bfced0ef0dc699f6a5-3 | Bin 0 -> 32 bytes .../5e701f4039d099c3a15c4e8d9b070eafc96de0e9 | 1 + .../5f9642a02959a51bf5a67e5347d702fe0ba6af79 | 1 + ...5fcc48ee5b52b608e5d909ca4eddae9bd8f3a6ae-8 | Bin 0 -> 11 bytes ...60031506809cb3ff39b549968772a652cdaf8e1d-1 | Bin 0 -> 981 bytes .../60df0cda93981b671836008ff12625cd51171e9d | Bin 0 -> 1776 bytes ...61077e99c801f3eb732ba4fae2296091eaea9c01-2 | Bin 0 -> 109 bytes ...612edfc64ec2f157158ac6b0b7bdceeb1338d3b8-6 | Bin 0 -> 8 bytes ...617132f8209014d1839691bc6c7d77e70ed60095-7 | Bin 0 -> 16 bytes ...6182f2935dfb8967ce0d259c3fbc143167528f3b-1 | 1 + .../64bd2417583750313dd74d25c8b2f3eed25909a8 | Bin 0 -> 670 bytes ...64dae3270e5806311fac4518cef7b473e2d3cd91-4 | 1 + ...67519fd21225a9a0f3c5a86a76de43fd7234e1d4-1 | 1 + ...6b8432daf9022411b253dd7c8f5611c22cdc3895-2 | 1 + .../6d44323de19d56374597e2ac06e3beee133a42df | 2 + ...72fa415daeee2a5f74a86a035e9dda32a29e34e4-2 | 1 + ...747e5c3eed27e2c0a7a8987c78981b9cece0150c-2 | 1 + ...780851224f52ce3b64a90ba56b4fc567aba4cd3d-1 | Bin 0 -> 132 bytes ...7d233588c41ecc575034228477393f70d8acb5fd-1 | Bin 0 -> 418 bytes .../7f255b276b164c4309adbab19b872422d979c5e5 | Bin 0 -> 1219 bytes ...7fca1fadd76fce238c82e9542eb05acd5bd38653-1 | 1 + ...8036c610dcec87d7bc42ba4ddddd660372392268-1 | Bin 0 -> 111 bytes ...82186327d4a14ac0da15581a5c7f37e83df72cf5-1 | 1 + ...85bb13fef173edaeb7be4e6675bf8374bf136d9c-1 | 1 + .../85d8aceca37403b2a0b6ed82502afd40f2513541 | Bin 0 -> 302 bytes ...872784ffeda8c586972151364e6917bc0fb463d2-4 | Bin 0 -> 33 bytes ...88b9cf63d84dab51dd67f44df0e64977da9dd7f2-3 | Bin 0 -> 23 bytes ...88c2814de9919316170e12c1cbe39ff2a4e3dc69-2 | Bin 0 -> 197 bytes ...89f86a63a2de2d2877451bceaa2bd4e38abc8e64-1 | Bin 0 -> 1648 bytes .../8c6d7def5f4465fc685347875a8e64e108b393df | 2 + ...8d43559e0f27f4a754db78baa697b37013f8a01d-1 | 1 + .../8d69ef1f7f28824fd8267ae8b36833e3e0b94765 | 1 + ...9239364aad81b3afb16be9487b5721a6fce7d375-2 | 1 + ...9508e90548b0440a4a61e5743b76c1e309b23b7f-3 | Bin 0 -> 3 bytes ...567d94166370de252e759169b215fa8c2288746-11 | Bin 0 -> 64 bytes ...962ecf57ef5bbb4107aaff02072f03d3316077c9-1 | Bin 0 -> 817 bytes .../96629c94c3faec6af9790f99bd72567d4534f9db | Bin 0 -> 980 bytes ...9aa393616dd8a00cd97be9a58bf70a9b4164d802-1 | Bin 0 -> 666 bytes ...9b3ec560e1ed89789a09e834a18fb9f1d042f5dd-2 | 1 + ...9c61b17678d14d0b9ae09be017c6bbd6a3c3cabe-1 | 1 + ...9e3fc7fad4bf135219a974a8dac87e366f5b8e8c-2 | 1 + .../a0bd71e19da9f0265508cdd2a50a458e5cd6bb19 | Bin 0 -> 1232 bytes ...a3c5cb453e89aef7359f952459685c26cea30d63-1 | Bin 0 -> 53 bytes .../a48f8d3562980d5cd8b9f0eb3859ee562d7c0596 | Bin 0 -> 981 bytes .../a5ef3d034850ec9510bb931f21a1547518a76f14 | 1 + ...a70573a8edabc05a2431773757158ac90e63d43a-1 | 1 + ...a8d099f456e0a9444c10bf1cdfe788da8f65f8d5-6 | Bin 0 -> 11 bytes ...a8d2bd34ee5b24064975a68298bfa566b63a133c-2 | 1 + .../ac04c28afed2d337f787d007a992e8ec7f937b36 | 1 + .../ad336c19a004476640934db99f827f2917a09bf8 | Bin 0 -> 17674 bytes ...aef8193ef7e7916cebd428e02ae7c9081b9e56a1-6 | Bin 0 -> 12 bytes .../af640328532d29ae2f935b87564cb595f6cbb54e | Bin 0 -> 1035 bytes .../b16d3306a414bbbffd9344eb00f460a160fb06bc | Bin 0 -> 504 bytes ...b585a3f5c60ffeef5d5bf13dccca17199d7ab311-2 | 1 + ...b776d26f33e5cb69dd1ee1bd66da9024509c62b6-1 | 1 + ...ba4b4565a95f651dd9c3e90b0742db3a422498e1-3 | 1 + .../bcd851430da545599a636bdf22499157116d652a | 1 + .../bd0ec04037fbff5629b94a88915ce29cfa3c9f9e | Bin 0 -> 9996 bytes .../bf297fbc5cd66aeca02688585a23f98a9f0081f5 | Bin 0 -> 878 bytes ...bf30493a58dc0fad8c77816086b2b32875cade69-1 | 1 + ...c05bf2b6c368beec9fe1ab4172da851e547b1e49-9 | 1 + .../c07ac5a6c29ec72f00d7fe9cfcd9900ebf6fcc1a | 1 + ...c4d93c018e1686a8e4aaf0a4dad8d60fecd13675-4 | Bin 0 -> 3 bytes ...c64b47ad9a354cefde19e93efca0d656a20fe024-6 | Bin 0 -> 4 bytes ...c6f1d808e0fd8c0a973e1b251e93ddae5930638e-1 | 1 + ...c7fd10d5817ad18dcb798e82328e8a7b087fbbea-1 | Bin 0 -> 928 bytes .../cb7cd34cfe31060ee210487d4d2eb6c1811e67c5 | Bin 0 -> 606 bytes .../cc6c7d741d3c9c4c6ceb1461068d6ec970805e3d | Bin 0 -> 755 bytes ...cdd398e0ae2a152bcb53d296a63e1e8ccaabb75b-3 | Bin 0 -> 1098 bytes .../d2142c494b1f6526189f383e88037cd4c05e16bb | 1 + ...d237dcb7a55a9542fbe886c9631804dea200b56a-2 | Bin 0 -> 504 bytes ...d38389226ead13791d80008cc5fb1eef75aa0be4-6 | Bin 0 -> 11 bytes ...d977ecea3fcbb78028aabdb98bf098594d5eaba7-2 | Bin 0 -> 544 bytes .../da39a3ee5e6b4b0d3255bfef95601890afd80709 | 0 ...dba30063a9e305d125c83f435e35e0aaa33c560c-1 | Bin 0 -> 1086 bytes .../dc2f0ff7f3e2d2a2b290bf36e85c695506c68782 | 1 + .../ddaf0bfb51c7134e58a010fe0a099e76e7bca7f6 | Bin 0 -> 1178 bytes ...ddc3609a7e8f2da5428973c80847b1ae0bc74af7-4 | 1 + ...dde60ed75565b253fc44c8543a788dbef7b9a53f-2 | Bin 0 -> 47 bytes ...e1170c6fe09522cb50935557856ba9d85c2b37de-3 | 1 + ...e1323173b156c91190a3b84ca33c955550404ade-2 | Bin 0 -> 36 bytes .../e295ba780df856ae31513226b96e8382063d034d | Bin 0 -> 1192 bytes ...e36bba8cd1c971edf6696aa76dfaf690e21e08c3-5 | Bin 0 -> 4 bytes .../e4862372d6534ac4eb19df7d21840887b8297df8 | 1 + .../e6722bb760655d9d3dbbdc4f9ebf7354a2461d97 | Bin 0 -> 600 bytes ...e77ce13737af5a84c7a50d9d18a6699fb862c63b-3 | 1 + ...e85ca8b54d82486ba7462ea0659c42a0a36cdb71-8 | Bin 0 -> 32 bytes ...ea616ea4310406f7893091a96e87e0b9c0412e4b-1 | Bin 0 -> 739 bytes ...ed0f1c5ee2700c3c2d9a0914de90363e750c3f47-3 | 2 + ...ee481cbb8636f3957618b3e627cc6a56caa1dce5-1 | Bin 0 -> 1593 bytes ...efa3bc9831786d0e203957fd2ac2c4de9d5c168a-2 | 1 + ...f0121676050a7bb84ade5c4783407e0527ca88a4-3 | 1 + ...f0bd04a4f5ccd427cf59b79e2f67caafdbfa0233-3 | Bin 0 -> 792 bytes ...f2a68d20b1e145bbf69037f17685e0adedfe68a4-6 | Bin 0 -> 11 bytes ...f320b3ab9e260a1bbd378762c54a8e23f794901a-2 | 1 + .../f5829f8a97a0a1dc008752245b460db0a0459c03 | Bin 0 -> 583 bytes ...f62e0a3c0c8bd15aa0b2f991898f2d27d2964d44-2 | 1 + ...f670ffe6dc8a8e0b45bfa675672498f90b44001e-2 | 1 + .../f7a76f4c851f342d0d576ffa71329438e109347c | Bin 0 -> 1647 bytes ...f8d134ecc8e30461236ed7b28aeb29bc2987e50e-1 | 1 + .../ffc64298b00af19e0f953728f42fa8e915d7b470 | 1 + ...0018ebe176ab4fa757c5da39cd8b2270f12de24-10 | Bin 0 -> 9 bytes ...0170787897b2aec4a4477ab507777ad13eb00e10-1 | Bin 0 -> 54 bytes ...0297e0b01e8ace9ec3a22311966681bbe06b875f-5 | Bin 0 -> 2 bytes ...04bc4648208f40ba61ffb9a929f760c24101522c-1 | Bin 0 -> 1278 bytes ...c4648208f40ba61ffb9a929f760c24101522c-1-4x | Bin 0 -> 1285 bytes ...04fe6043558c921672856d1d9332bb41b7d64087-2 | 1 + ...05575bdaa6ba33f22d304f9f3a62010e42f76acf-2 | Bin 0 -> 90 bytes .../0a7ce59229caf93ee64d5a828aecab7b5e434bbc | Bin 0 -> 501 bytes ...a7ce59229caf93ee64d5a828aecab7b5e434bbc-4x | Bin 0 -> 507 bytes .../0ceda9053c751bf974334c7c1676832feea92d69 | Bin 0 -> 1569 bytes ...ceda9053c751bf974334c7c1676832feea92d69-4x | Bin 0 -> 1577 bytes ...0e90b9893889f69194ca72e28082a1f6081c4b35-1 | Bin 0 -> 16 bytes ...0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 | 1 + ...1050baf5be0eeaa50c7e2ccd22c386146d582668-5 | 1 + ...112b9d35e8cbeabce6fda543aec804ab83185543-1 | Bin 0 -> 52 bytes ...b9d35e8cbeabce6fda543aec804ab83185543-1-4x | Bin 0 -> 59 bytes ...118873131212b4f8e4f2b7aa9e398911bf83fb21-2 | Bin 0 -> 9 bytes ...12a386209a550aec21fbfa0b2ec8c066fe131db7-2 | Bin 0 -> 12 bytes ...17a53cfc55c261af6e258f0effbe34a9d0c3a117-2 | Bin 0 -> 19 bytes ...182516c486b2eafc720a03046af1949a758ff7b4-3 | 1 + ...1e23aabdf832d3bd167105c98f4931313e0df945-8 | 1 + .../1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 | Bin 0 -> 78 bytes ...223bb6b768c691e0f2eb62db5821b8678a9ecc93-3 | 1 + ...2273a03f5b8fe56f4bbb7f7e9560c440fb8237c8-5 | Bin 0 -> 30 bytes .../234ec5ad1fc105fcc08523ff91bd8430284aa1f3 | Bin 0 -> 100227 bytes ...34ec5ad1fc105fcc08523ff91bd8430284aa1f3-4x | Bin 0 -> 100235 bytes ...236bd270f4d36e14eaf41daf5bf33e55ff5f463d-6 | 1 + ...269f2e5e3b3b1acba92aefd0a49444d0869af5ae-7 | 1 + ...2805bdad6bc68c3c6edd9344d658b6d43a8dbcbc-3 | 1 + ...187c5cc2c8b927997cbd46e9328581620116613-12 | Bin 0 -> 23 bytes ...34e0f846cc18c5c0a6e0334192411dc2c6a1c719-7 | 1 + ...36971f66110d363f2a217d16bf1913475c25a862-3 | Bin 0 -> 90 bytes ...38729163260fdf7a5526f17de3cb34f02661e8c9-1 | Bin 0 -> 28 bytes ...3885c38b78f31c98dd73bc1fa7d6dfe467eb0fa4-3 | Bin 0 -> 90 bytes ...3aa823c93e1ed004c38d32fc9f96c9f6036e7c77-5 | 1 + ...c48a486a1b94dc9df2201c25f411123cedd119c-10 | 1 + ...3cee784d376938121b711cd56f71a68f3496cda8-4 | Bin 0 -> 90 bytes ...f85a2df398429128e89cb13f51f612645550408-11 | Bin 0 -> 15 bytes .../40b8de701a171fddefdc4459023121a1e605b16c | Bin 0 -> 156 bytes ...0b8de701a171fddefdc4459023121a1e605b16c-4x | Bin 0 -> 164 bytes ...40fbf19f5ba46c802a2755c71c852b92fc334dd4-2 | Bin 0 -> 18 bytes ...4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 | Bin 0 -> 943 bytes ...6d42682c6b5f9f068148a3d94f5b52d9a2862-1-4x | Bin 0 -> 951 bytes .../43726b29460c5060782f19cb0facac8443ad5d0b | Bin 0 -> 513 bytes ...3726b29460c5060782f19cb0facac8443ad5d0b-4x | Bin 0 -> 520 bytes .../43a26357597ae65521480220432ff645450d01f1 | Bin 0 -> 1115 bytes ...3a26357597ae65521480220432ff645450d01f1-4x | Bin 0 -> 1122 bytes ...44678db801ad65c4ba51cc5e0cd9095852f329cd-9 | 1 + ...46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 | 3 + ...475dfd55b54d9a0a4287ab8b952f606f2773a49c-1 | Bin 0 -> 1122 bytes .../4869e00fbc61867ccab5b83187c3a146ecb36775 | Bin 0 -> 817 bytes ...869e00fbc61867ccab5b83187c3a146ecb36775-4x | Bin 0 -> 825 bytes ...489bdb7862474650462b753ed85d2a123d1730ca-2 | 1 + ...4bb7d1adac51afa9ac4650ee8ae5203297aa8fec-4 | Bin 0 -> 18 bytes ...542e60846887c634378dd1b29d3ce29b90e13f99-6 | 1 + ...54fbf0fc6ed4319b2c0986f26c3a142b194d9ca3-4 | Bin 0 -> 3 bytes ...5889a9b84fb69d2913d474a381ddceb217137d06-1 | Bin 0 -> 100238 bytes ...5b85e7d11f14ff2864b2c56e03188f15e52fd9bb-8 | 1 + ...649971daa4b93c4ffe6190415f22569030f2300a-3 | Bin 0 -> 34 bytes ...6903fccf79c27b4cffe21090d03c6879cbb72274-6 | Bin 0 -> 10 bytes ...695a09b31703a8f7f00422a62549912c31263506-3 | Bin 0 -> 34 bytes ...6a88ce804bf81bb01a233527595b27668cca331d-1 | Bin 0 -> 131073 bytes ...6c16b84194ac60c492487044ed3ee744c506faf6-2 | 1 + ...6cdd7b3f70c2448bb4f666c8bc5aa6a890a34f7a-3 | Bin 0 -> 27 bytes ...73e369adcad522a27653be74fe4a9ff8d30ea19e-7 | 1 + ...7f1623aee483c22124f8ecd37ad62c5acc932304-4 | Bin 0 -> 39 bytes ...87e26a4d86b6f1ffba523d73bdf7479715faa6c0-5 | Bin 0 -> 10 bytes ...8af40c705337fe65b50643a231029a953ea998af-5 | 1 + ...913987cb3ea3aa8df9fabade3b6440bfb0e14019-1 | Bin 0 -> 53 bytes ...4b18a8ac5c2cd3b040754e236dadeae895b3dae-13 | Bin 0 -> 10 bytes ...9835e8bdcd54890f9ff4dfdb634b5a6dc254f09e-2 | 1 + ...9f3d543656b54b38ac84f009a626bdfb074393cb-2 | Bin 0 -> 18 bytes ...a70fe33ef1a23361593e5d25ed782c2b4ee22813-1 | Bin 0 -> 18 bytes ...ab076dfc3f75d3a603806cbf3ab318bab8575591-7 | 1 + ...ac8feec2af44db5a6eafff09781dc9c922fc1380-4 | 1 + ...aeb91ce9a4b3547b57a3ab02add1500b6d6447a8-4 | Bin 0 -> 28 bytes ...af04c0ac0c9608e913ab0f27a1426630adc72f57-8 | 1 + ...b8fceb6a5aa974b33d2dc94526c96a3d46633e89-4 | 1 + ...ba01d6cf0fb9c71370ef35d6c6cebb1fa75018f6-5 | Bin 0 -> 10 bytes ...bf49b2edbbb9da8b0c135b3ed5e5a5a7e77e61a9-2 | 1 + ...c03c780b2d547bf3157d929730d554533b570acc-6 | 1 + ...c37533eda04d4cd770cce546fd0db044407d765c-1 | Bin 0 -> 13693 bytes ...c3793d6b45cba4a91dc18770c1c2a9946d334258-1 | Bin 0 -> 86784 bytes ...9d84a90c00d2393354dd80dbb9d26e8edd387e0-10 | 1 + ...d06c109bc27d8914b330b99ac8262cbceda79b4f-1 | 1 + ...d1f80ef35b58a2366e5b133473dc273f3740d57b-7 | 1 + ...d2e694ef05e527e478769df82b0f65fb3b442a45-1 | Bin 0 -> 506 bytes ...da39a3ee5e6b4b0d3255bfef95601890afd80709-2 | 0 ...db3bda50ea81814214d6e6c511736731a44d7b9a-2 | Bin 0 -> 76 bytes ...ddf623fc42f256fbee77d98e0c341d8f8e967d6f-6 | Bin 0 -> 13 bytes ...e7416101c16988f1aa4ad09e2e0ea26698a69fd5-6 | 1 + ...eae606b8c2871f94da1b8190d095e686e9f2eebc-5 | Bin 0 -> 90 bytes ...ec2c23b0ecfb55422bb7376b9de762f0cb2daabc-5 | Bin 0 -> 90 bytes ...ee5e3543ec53aa392b7485e16163661dc45c61b8-3 | Bin 0 -> 18 bytes ...f317ba679fa2f7020fd501a5ceb78a12da06a817-4 | Bin 0 -> 90 bytes ...fa0258e24eecdba8b3e9355740c458120b4babce-7 | 1 + ...fab8c92bc4068e05f10d9b1978a34bfd5a0c12da-4 | 1 + .../compress/huff0/fuzz/run-compress.cmd | 4 + .../compress/huff0/fuzz/run-decompress.cmd | 4 + .../klauspost/compress/huff0/fuzz_compress.go | 27 + .../compress/huff0/fuzz_decompress.go | 16 + .../klauspost/compress/huff0/highbit_go19.go | 9 + .../klauspost/compress/huff0/highbit_old.go | 18 + .../klauspost/compress/huff0/huff0.go | 232 + .../klauspost/compress/testdata/case1.bin | Bin 0 -> 55 bytes .../klauspost/compress/testdata/case2.bin | 1 + .../klauspost/compress/testdata/case3.bin | 1 + .../klauspost/compress/testdata/crash1.bin | Bin 0 -> 5 bytes .../klauspost/compress/testdata/crash2.bin | 1 + .../klauspost/compress/testdata/crash3.bin | 1 + .../klauspost/compress/testdata/crash4.bin | 1 + .../klauspost/compress/testdata/crash5.bin | 1 + .../klauspost/compress/testdata/dec-hang1.bin | 1 + .../klauspost/compress/testdata/dec-hang2.bin | 1 + .../klauspost/compress/testdata/dec-hang3.bin | 1 + .../compress/testdata/dec-symlen1.bin | Bin 0 -> 49 bytes .../compress/testdata/endnonzero.bin | Bin 0 -> 7 bytes .../compress/testdata/endzerobits.bin | Bin 0 -> 5 bytes .../compress/testdata/normcount2.bin | 1 + .../klauspost/compress/testdata/pngdata.bin | Bin 0 -> 51200 bytes .../klauspost/compress/testdata/sharnd.out | Bin 0 -> 100004 bytes .../klauspost/compress/zip/reader.go | 3 +- .../klauspost/compress/zip/writer.go | 3 +- .../klauspost/compress/zlib/reader.go | 9 +- vendor/github.com/klauspost/crc32/.gitignore | 24 - vendor/github.com/klauspost/crc32/.travis.yml | 13 - vendor/github.com/klauspost/crc32/README.md | 87 - vendor/github.com/klauspost/crc32/crc32.go | 207 - .../github.com/klauspost/crc32/crc32_amd64.go | 230 - .../github.com/klauspost/crc32/crc32_amd64.s | 319 - .../klauspost/crc32/crc32_amd64p32.go | 43 - .../klauspost/crc32/crc32_amd64p32.s | 67 - .../klauspost/crc32/crc32_generic.go | 89 - .../klauspost/crc32/crc32_otherarch.go | 15 - .../github.com/klauspost/crc32/crc32_s390x.go | 91 - .../github.com/klauspost/crc32/crc32_s390x.s | 249 - .../github.com/klauspost/crc32/crc32_test.go | 284 - .../klauspost/crc32/example_test.go | 28 - vendor/github.com/lib/pq/.travis.sh | 12 - vendor/github.com/lib/pq/.travis.yml | 16 +- vendor/github.com/lib/pq/README.md | 13 +- vendor/github.com/lib/pq/TESTS.md | 33 + vendor/github.com/lib/pq/bench_test.go | 5 +- vendor/github.com/lib/pq/conn.go | 39 +- vendor/github.com/lib/pq/conn_go18.go | 5 +- vendor/github.com/lib/pq/conn_test.go | 67 +- vendor/github.com/lib/pq/connector.go | 43 + .../lib/pq/connector_example_test.go | 33 + vendor/github.com/lib/pq/connector_test.go | 67 + vendor/github.com/lib/pq/copy_test.go | 15 +- vendor/github.com/lib/pq/encode_test.go | 27 +- vendor/github.com/lib/pq/error.go | 8 +- vendor/github.com/lib/pq/go18_test.go | 4 +- vendor/github.com/lib/pq/notify.go | 6 +- vendor/github.com/lib/pq/ssl.go | 57 +- vendor/github.com/mattn/go-sqlite3/.gitignore | 10 + .../github.com/mattn/go-sqlite3/.travis.yml | 48 +- vendor/github.com/mattn/go-sqlite3/README.md | 485 +- .../mattn/go-sqlite3/_example/trace/main.go | 2 +- .../github.com/mattn/go-sqlite3/callback.go | 10 + .../mattn/go-sqlite3/sqlite3-binding.c | 17357 +++++++++----- .../mattn/go-sqlite3/sqlite3-binding.h | 1015 +- vendor/github.com/mattn/go-sqlite3/sqlite3.go | 805 +- .../mattn/go-sqlite3/sqlite3_func_crypt.go | 120 + .../go-sqlite3/sqlite3_func_crypt_test.go | 57 + .../mattn/go-sqlite3/sqlite3_go18.go | 1 + .../mattn/go-sqlite3/sqlite3_go18_test.go | 1 - .../mattn/go-sqlite3/sqlite3_libsqlite3.go | 2 + .../go-sqlite3/sqlite3_load_extension.go | 1 + ...sion.go => sqlite3_load_extension_omit.go} | 1 + .../sqlite3_opt_allow_uri_authority.go | 15 + .../mattn/go-sqlite3/sqlite3_opt_app_armor.go | 16 + .../go-sqlite3/sqlite3_opt_foreign_keys.go | 15 + ..._fts3_test.go => sqlite3_opt_fts3_test.go} | 0 .../{sqlite3_fts5.go => sqlite3_opt_fts5.go} | 3 +- .../{sqlite3_icu.go => sqlite3_opt_icu.go} | 6 +- .../go-sqlite3/sqlite3_opt_introspect.go | 15 + ...{sqlite3_json1.go => sqlite3_opt_json1.go} | 3 +- .../go-sqlite3/sqlite3_opt_secure_delete.go | 15 + .../sqlite3_opt_secure_delete_fast.go | 15 + .../mattn/go-sqlite3/sqlite3_opt_stat4.go | 15 + .../mattn/go-sqlite3/sqlite3_opt_userauth.go | 289 + .../go-sqlite3/sqlite3_opt_userauth_omit.go | 152 + .../go-sqlite3/sqlite3_opt_userauth_test.go | 619 + .../go-sqlite3/sqlite3_opt_vacuum_full.go | 15 + .../go-sqlite3/sqlite3_opt_vacuum_incr.go | 15 + ...qlite3_vtable.go => sqlite3_opt_vtable.go} | 10 +- ...ble_test.go => sqlite3_opt_vtable_test.go} | 3 +- .../mattn/go-sqlite3/sqlite3_other.go | 2 +- .../mattn/go-sqlite3/sqlite3_solaris.go | 14 + .../mattn/go-sqlite3/sqlite3_test.go | 130 +- .../mattn/go-sqlite3/sqlite3_trace.go | 25 +- .../go-sqlite3/sqlite3_usleep_windows.go | 39 + .../mattn/go-sqlite3/sqlite3_windows.go | 8 +- .../github.com/mattn/go-sqlite3/sqlite3ext.h | 37 + .../mattn/go-sqlite3/static_mock.go | 21 + .../mattn/go-sqlite3/tool/upgrade.go | 111 - .../mattn/go-sqlite3/upgrade/package.go | 7 + .../mattn/go-sqlite3/upgrade/upgrade.go | 218 + vendor/github.com/miekg/dns/Makefile.release | 1 + vendor/github.com/miekg/dns/README.md | 2 + vendor/github.com/miekg/dns/client.go | 102 +- vendor/github.com/miekg/dns/client_test.go | 22 + vendor/github.com/miekg/dns/clientconfig.go | 2 +- .../github.com/miekg/dns/clientconfig_test.go | 28 + .../github.com/miekg/dns/compress_generate.go | 28 +- vendor/github.com/miekg/dns/dns.go | 10 - vendor/github.com/miekg/dns/dns_test.go | 146 - vendor/github.com/miekg/dns/dnssec.go | 23 +- vendor/github.com/miekg/dns/dnssec_test.go | 19 + vendor/github.com/miekg/dns/doc.go | 4 +- vendor/github.com/miekg/dns/edns.go | 7 +- vendor/github.com/miekg/dns/leak_test.go | 1 + vendor/github.com/miekg/dns/length_test.go | 371 + vendor/github.com/miekg/dns/msg.go | 160 +- vendor/github.com/miekg/dns/msg_helpers.go | 10 +- vendor/github.com/miekg/dns/msg_test.go | 22 + vendor/github.com/miekg/dns/nsecx_test.go | 8 + vendor/github.com/miekg/dns/privaterr.go | 3 +- vendor/github.com/miekg/dns/scan_rr.go | 12 +- vendor/github.com/miekg/dns/server.go | 204 +- vendor/github.com/miekg/dns/server_test.go | 43 +- vendor/github.com/miekg/dns/types_generate.go | 2 +- vendor/github.com/miekg/dns/udp.go | 33 +- vendor/github.com/miekg/dns/udp_test.go | 14 + vendor/github.com/miekg/dns/version.go | 2 +- vendor/github.com/miekg/dns/zcompress.go | 165 +- vendor/github.com/miekg/dns/ztypes.go | 130 +- vendor/github.com/rs/cors/.travis.yml | 3 +- vendor/github.com/rs/cors/README.md | 15 +- vendor/github.com/rs/cors/cors.go | 44 +- vendor/github.com/rs/cors/cors_test.go | 27 +- .../rs/cors/examples/buffalo/server.go | 36 + .../github.com/rs/cors/examples/gin/server.go | 19 + vendor/github.com/rs/cors/go.mod | 1 + vendor/github.com/rs/cors/wrapper/gin/gin.go | 50 + .../rs/cors/wrapper/gin/gin_test.go | 76 + vendor/github.com/satori/go.uuid/.travis.yml | 23 - vendor/github.com/satori/go.uuid/LICENSE | 20 - vendor/github.com/satori/go.uuid/README.md | 65 - vendor/github.com/satori/go.uuid/codec.go | 206 - .../github.com/satori/go.uuid/codec_test.go | 248 - vendor/github.com/satori/go.uuid/generator.go | 239 - .../satori/go.uuid/generator_test.go | 134 - vendor/github.com/satori/go.uuid/sql.go | 78 - vendor/github.com/satori/go.uuid/sql_test.go | 136 - vendor/github.com/satori/go.uuid/uuid.go | 161 - vendor/github.com/satori/go.uuid/uuid_test.go | 90 - vendor/github.com/sirupsen/logrus/.travis.yml | 6 +- .../github.com/sirupsen/logrus/CHANGELOG.md | 5 + vendor/github.com/sirupsen/logrus/README.md | 60 +- vendor/github.com/sirupsen/logrus/entry.go | 69 +- .../github.com/sirupsen/logrus/entry_test.go | 38 + vendor/github.com/sirupsen/logrus/exported.go | 20 +- .../github.com/sirupsen/logrus/formatter.go | 20 +- .../sirupsen/logrus/hooks/test/test.go | 15 +- .../sirupsen/logrus/hooks/test/test_test.go | 38 +- .../sirupsen/logrus/json_formatter.go | 12 +- .../sirupsen/logrus/json_formatter_test.go | 97 + vendor/github.com/sirupsen/logrus/logger.go | 16 +- .../github.com/sirupsen/logrus/logrus_test.go | 60 + .../sirupsen/logrus/terminal_bsd.go | 2 +- .../logrus/terminal_check_appengine.go | 2 +- .../logrus/terminal_check_notappengine.go | 2 +- .../sirupsen/logrus/terminal_linux.go | 2 +- .../sirupsen/logrus/text_formatter.go | 31 +- .../sirupsen/logrus/text_formatter_test.go | 79 + .../github.com/stretchr/testify/.travis.yml | 8 +- vendor/github.com/stretchr/testify/Gopkg.lock | 8 +- vendor/github.com/stretchr/testify/Gopkg.toml | 36 +- vendor/github.com/stretchr/testify/README.md | 55 +- .../testify/assert/assertion_format.go | 201 +- .../testify/assert/assertion_format.go.tmpl | 1 + .../testify/assert/assertion_forward.go | 402 +- .../testify/assert/assertion_forward.go.tmpl | 1 + .../stretchr/testify/assert/assertions.go | 280 +- .../testify/assert/assertions_test.go | 216 +- .../testify/assert/http_assertions.go | 22 +- .../testify/assert/http_assertions_test.go | 29 + .../github.com/stretchr/testify/mock/mock.go | 129 +- .../stretchr/testify/mock/mock_test.go | 167 +- .../stretchr/testify/require/require.go | 852 +- .../stretchr/testify/require/require.go.tmpl | 6 +- .../testify/require/require_forward.go | 402 +- .../testify/require/require_forward.go.tmpl | 1 + .../stretchr/testify/require/requirements.go | 20 + .../testify/require/requirements_test.go | 197 + .../xeipuuv/gojsonpointer/README.md | 33 + .../xeipuuv/gojsonpointer/pointer.go | 21 + .../xeipuuv/gojsonpointer/pointer_test.go | 100 + .../xeipuuv/gojsonreference/reference.go | 18 +- .../xeipuuv/gojsonreference/reference_test.go | 20 +- .../xeipuuv/gojsonschema/.gitignore | 2 + .../xeipuuv/gojsonschema/.travis.yml | 6 +- .../github.com/xeipuuv/gojsonschema/README.md | 64 +- .../github.com/xeipuuv/gojsonschema/errors.go | 45 +- .../xeipuuv/gojsonschema/format_checkers.go | 16 +- .../xeipuuv/gojsonschema/glide.yaml | 7 +- .../xeipuuv/gojsonschema/jsonContext.go | 16 +- .../xeipuuv/gojsonschema/jsonLoader.go | 33 +- .../json_schema_test_suite/LICENSE | 19 - .../additionalItems/data_00.json | 1 - .../additionalItems/data_01.json | 1 - .../additionalItems/data_10.json | 1 - .../additionalItems/data_20.json | 1 - .../additionalItems/data_21.json | 1 - .../additionalItems/data_30.json | 1 - .../additionalItems/data_31.json | 1 - .../additionalItems/data_40.json | 1 - .../additionalItems/schema_0.json | 1 - .../additionalItems/schema_1.json | 1 - .../additionalItems/schema_2.json | 1 - .../additionalItems/schema_3.json | 1 - .../additionalItems/schema_4.json | 1 - .../additionalProperties/data_00.json | 1 - .../additionalProperties/data_01.json | 1 - .../additionalProperties/data_02.json | 1 - .../additionalProperties/data_03.json | 1 - .../additionalProperties/data_10.json | 1 - .../additionalProperties/data_11.json | 1 - .../additionalProperties/data_12.json | 1 - .../additionalProperties/data_20.json | 1 - .../additionalProperties/schema_0.json | 1 - .../additionalProperties/schema_1.json | 1 - .../additionalProperties/schema_2.json | 1 - .../json_schema_test_suite/allOf/data_00.json | 1 - .../json_schema_test_suite/allOf/data_01.json | 1 - .../json_schema_test_suite/allOf/data_02.json | 1 - .../json_schema_test_suite/allOf/data_03.json | 1 - .../json_schema_test_suite/allOf/data_10.json | 1 - .../json_schema_test_suite/allOf/data_11.json | 1 - .../json_schema_test_suite/allOf/data_12.json | 1 - .../json_schema_test_suite/allOf/data_13.json | 1 - .../json_schema_test_suite/allOf/data_14.json | 1 - .../json_schema_test_suite/allOf/data_20.json | 1 - .../json_schema_test_suite/allOf/data_21.json | 1 - .../allOf/schema_0.json | 1 - .../allOf/schema_1.json | 1 - .../allOf/schema_2.json | 1 - .../json_schema_test_suite/anyOf/data_00.json | 1 - .../json_schema_test_suite/anyOf/data_01.json | 1 - .../json_schema_test_suite/anyOf/data_02.json | 1 - .../json_schema_test_suite/anyOf/data_03.json | 1 - .../json_schema_test_suite/anyOf/data_10.json | 1 - .../json_schema_test_suite/anyOf/data_11.json | 1 - .../json_schema_test_suite/anyOf/data_12.json | 1 - .../anyOf/schema_0.json | 1 - .../anyOf/schema_1.json | 1 - .../definitions/data_00.json | 1 - .../definitions/data_10.json | 1 - .../definitions/schema_0.json | 1 - .../definitions/schema_1.json | 1 - .../dependencies/data_00.json | 1 - .../dependencies/data_01.json | 1 - .../dependencies/data_02.json | 1 - .../dependencies/data_03.json | 1 - .../dependencies/data_04.json | 1 - .../dependencies/data_10.json | 1 - .../dependencies/data_11.json | 1 - .../dependencies/data_12.json | 1 - .../dependencies/data_13.json | 1 - .../dependencies/data_14.json | 1 - .../dependencies/data_15.json | 1 - .../dependencies/data_20.json | 1 - .../dependencies/data_21.json | 1 - .../dependencies/data_22.json | 1 - .../dependencies/data_23.json | 1 - .../dependencies/data_24.json | 1 - .../dependencies/schema_0.json | 1 - .../dependencies/schema_1.json | 1 - .../dependencies/schema_2.json | 1 - .../json_schema_test_suite/enum/data_00.json | 1 - .../json_schema_test_suite/enum/data_01.json | 1 - .../json_schema_test_suite/enum/data_10.json | 1 - .../json_schema_test_suite/enum/data_11.json | 1 - .../json_schema_test_suite/enum/data_12.json | 1 - .../json_schema_test_suite/enum/schema_0.json | 1 - .../json_schema_test_suite/enum/schema_1.json | 1 - .../format/data_00.json | 1 - .../format/data_01.json | 1 - .../format/data_02.json | 1 - .../format/data_03.json | 1 - .../format/data_04.json | 1 - .../format/data_05.json | 1 - .../format/data_06.json | 1 - .../format/data_07.json | 1 - .../format/data_08.json | 1 - .../format/data_09.json | 1 - .../format/data_10.json | 1 - .../format/data_11.json | 1 - .../format/data_12.json | 1 - .../format/data_14.json | 1 - .../format/data_15.json | 1 - .../format/data_16.json | 1 - .../format/data_17.json | 1 - .../format/data_18.json | 1 - .../format/data_19.json | 1 - .../format/data_20.json | 1 - .../format/data_21.json | 1 - .../format/data_22.json | 1 - .../format/data_23.json | 1 - .../format/data_24.json | 1 - .../format/data_25.json | 1 - .../format/data_26.json | 1 - .../format/data_27.json | 1 - .../format/data_28.json | 1 - .../format/data_29.json | 1 - .../format/data_30.json | 1 - .../format/schema_0.json | 1 - .../format/schema_1.json | 1 - .../format/schema_2.json | 1 - .../format/schema_3.json | 1 - .../format/schema_4.json | 1 - .../format/schema_5.json | 1 - .../format/schema_6.json | 1 - .../format/schema_7.json | 1 - .../json_schema_test_suite/items/data_00.json | 1 - .../json_schema_test_suite/items/data_01.json | 1 - .../json_schema_test_suite/items/data_02.json | 1 - .../json_schema_test_suite/items/data_10.json | 1 - .../json_schema_test_suite/items/data_11.json | 1 - .../items/schema_0.json | 1 - .../items/schema_1.json | 1 - .../maxItems/data_00.json | 1 - .../maxItems/data_01.json | 1 - .../maxItems/data_02.json | 1 - .../maxItems/data_03.json | 1 - .../maxItems/schema_0.json | 1 - .../maxLength/data_00.json | 1 - .../maxLength/data_01.json | 1 - .../maxLength/data_02.json | 1 - .../maxLength/data_03.json | 1 - .../maxLength/data_04.json | 1 - .../maxLength/schema_0.json | 1 - .../maxProperties/data_00.json | 1 - .../maxProperties/data_01.json | 1 - .../maxProperties/data_02.json | 1 - .../maxProperties/data_03.json | 1 - .../maxProperties/schema_0.json | 1 - .../maximum/data_00.json | 1 - .../maximum/data_01.json | 1 - .../maximum/data_02.json | 1 - .../maximum/data_10.json | 1 - .../maximum/data_11.json | 1 - .../maximum/schema_0.json | 1 - .../maximum/schema_1.json | 1 - .../minItems/data_00.json | 1 - .../minItems/data_01.json | 1 - .../minItems/data_02.json | 1 - .../minItems/data_03.json | 1 - .../minItems/schema_0.json | 1 - .../minLength/data_00.json | 1 - .../minLength/data_01.json | 1 - .../minLength/data_02.json | 1 - .../minLength/data_03.json | 1 - .../minLength/data_04.json | 1 - .../minLength/schema_0.json | 1 - .../minProperties/data_00.json | 1 - .../minProperties/data_01.json | 1 - .../minProperties/data_02.json | 1 - .../minProperties/data_03.json | 1 - .../minProperties/schema_0.json | 1 - .../minimum/data_00.json | 1 - .../minimum/data_01.json | 1 - .../minimum/data_02.json | 1 - .../minimum/data_10.json | 1 - .../minimum/data_11.json | 1 - .../minimum/schema_0.json | 1 - .../minimum/schema_1.json | 1 - .../multipleOf/data_00.json | 1 - .../multipleOf/data_01.json | 1 - .../multipleOf/data_02.json | 1 - .../multipleOf/data_10.json | 1 - .../multipleOf/data_11.json | 1 - .../multipleOf/data_12.json | 1 - .../multipleOf/data_20.json | 1 - .../multipleOf/data_21.json | 1 - .../multipleOf/schema_0.json | 1 - .../multipleOf/schema_1.json | 1 - .../multipleOf/schema_2.json | 1 - .../json_schema_test_suite/not/data_00.json | 1 - .../json_schema_test_suite/not/data_01.json | 1 - .../json_schema_test_suite/not/data_10.json | 1 - .../json_schema_test_suite/not/data_11.json | 1 - .../json_schema_test_suite/not/data_12.json | 1 - .../json_schema_test_suite/not/data_20.json | 1 - .../json_schema_test_suite/not/data_21.json | 1 - .../json_schema_test_suite/not/data_22.json | 1 - .../json_schema_test_suite/not/schema_0.json | 1 - .../json_schema_test_suite/not/schema_1.json | 1 - .../json_schema_test_suite/not/schema_2.json | 1 - .../json_schema_test_suite/oneOf/data_00.json | 1 - .../json_schema_test_suite/oneOf/data_01.json | 1 - .../json_schema_test_suite/oneOf/data_02.json | 1 - .../json_schema_test_suite/oneOf/data_03.json | 1 - .../json_schema_test_suite/oneOf/data_10.json | 1 - .../json_schema_test_suite/oneOf/data_11.json | 1 - .../json_schema_test_suite/oneOf/data_12.json | 1 - .../oneOf/schema_0.json | 1 - .../oneOf/schema_1.json | 1 - .../pattern/data_00.json | 1 - .../pattern/data_01.json | 1 - .../pattern/data_02.json | 1 - .../pattern/schema_0.json | 1 - .../patternProperties/data_00.json | 1 - .../patternProperties/data_01.json | 1 - .../patternProperties/data_02.json | 1 - .../patternProperties/data_03.json | 1 - .../patternProperties/data_04.json | 1 - .../patternProperties/data_10.json | 1 - .../patternProperties/data_11.json | 1 - .../patternProperties/data_12.json | 1 - .../patternProperties/data_13.json | 1 - .../patternProperties/data_14.json | 1 - .../patternProperties/data_15.json | 1 - .../patternProperties/data_20.json | 1 - .../patternProperties/data_21.json | 1 - .../patternProperties/data_22.json | 1 - .../patternProperties/data_23.json | 1 - .../patternProperties/data_24.json | 4 - .../patternProperties/data_25.json | 3 - .../patternProperties/data_26.json | 6 - .../patternProperties/schema_0.json | 1 - .../patternProperties/schema_1.json | 1 - .../patternProperties/schema_2.json | 1 - .../patternProperties/schema_3.json | 8 - .../patternProperties/schema_4.json | 14 - .../properties/data_00.json | 1 - .../properties/data_01.json | 1 - .../properties/data_02.json | 1 - .../properties/data_03.json | 1 - .../properties/data_04.json | 1 - .../properties/data_10.json | 1 - .../properties/data_11.json | 1 - .../properties/data_12.json | 1 - .../properties/data_13.json | 1 - .../properties/data_14.json | 1 - .../properties/data_15.json | 1 - .../properties/data_16.json | 1 - .../properties/data_17.json | 1 - .../properties/schema_0.json | 1 - .../properties/schema_1.json | 1 - .../json_schema_test_suite/ref/data_00.json | 1 - .../json_schema_test_suite/ref/data_01.json | 1 - .../json_schema_test_suite/ref/data_02.json | 1 - .../json_schema_test_suite/ref/data_03.json | 1 - .../json_schema_test_suite/ref/data_10.json | 1 - .../json_schema_test_suite/ref/data_11.json | 1 - .../json_schema_test_suite/ref/data_20.json | 1 - .../json_schema_test_suite/ref/data_21.json | 1 - .../json_schema_test_suite/ref/data_30.json | 1 - .../json_schema_test_suite/ref/data_31.json | 1 - .../json_schema_test_suite/ref/data_32.json | 1 - .../json_schema_test_suite/ref/data_40.json | 1 - .../json_schema_test_suite/ref/data_41.json | 1 - .../json_schema_test_suite/ref/data_50.json | 1 - .../json_schema_test_suite/ref/data_51.json | 1 - .../json_schema_test_suite/ref/schema_0.json | 1 - .../json_schema_test_suite/ref/schema_1.json | 1 - .../json_schema_test_suite/ref/schema_2.json | 1 - .../json_schema_test_suite/ref/schema_3.json | 1 - .../json_schema_test_suite/ref/schema_4.json | 1 - .../json_schema_test_suite/ref/schema_5.json | 1 - .../refRemote/data_00.json | 1 - .../refRemote/data_01.json | 1 - .../refRemote/data_10.json | 1 - .../refRemote/data_11.json | 1 - .../refRemote/data_20.json | 1 - .../refRemote/data_21.json | 1 - .../refRemote/data_30.json | 1 - .../refRemote/data_31.json | 1 - .../refRemote/schema_0.json | 1 - .../refRemote/schema_1.json | 1 - .../refRemote/schema_2.json | 1 - .../refRemote/schema_3.json | 1 - .../required/data_00.json | 1 - .../required/data_01.json | 1 - .../required/data_10.json | 1 - .../required/schema_0.json | 1 - .../required/schema_1.json | 1 - .../json_schema_test_suite/type/data_00.json | 1 - .../json_schema_test_suite/type/data_01.json | 1 - .../json_schema_test_suite/type/data_02.json | 1 - .../json_schema_test_suite/type/data_03.json | 1 - .../json_schema_test_suite/type/data_04.json | 1 - .../json_schema_test_suite/type/data_05.json | 1 - .../json_schema_test_suite/type/data_06.json | 1 - .../json_schema_test_suite/type/data_10.json | 1 - .../json_schema_test_suite/type/data_11.json | 1 - .../json_schema_test_suite/type/data_12.json | 1 - .../json_schema_test_suite/type/data_13.json | 1 - .../json_schema_test_suite/type/data_14.json | 1 - .../json_schema_test_suite/type/data_15.json | 1 - .../json_schema_test_suite/type/data_16.json | 1 - .../json_schema_test_suite/type/data_20.json | 1 - .../json_schema_test_suite/type/data_21.json | 1 - .../json_schema_test_suite/type/data_22.json | 1 - .../json_schema_test_suite/type/data_23.json | 1 - .../json_schema_test_suite/type/data_24.json | 1 - .../json_schema_test_suite/type/data_25.json | 1 - .../json_schema_test_suite/type/data_26.json | 1 - .../json_schema_test_suite/type/data_30.json | 1 - .../json_schema_test_suite/type/data_31.json | 1 - .../json_schema_test_suite/type/data_32.json | 1 - .../json_schema_test_suite/type/data_33.json | 1 - .../json_schema_test_suite/type/data_34.json | 1 - .../json_schema_test_suite/type/data_35.json | 1 - .../json_schema_test_suite/type/data_36.json | 1 - .../json_schema_test_suite/type/data_40.json | 1 - .../json_schema_test_suite/type/data_41.json | 1 - .../json_schema_test_suite/type/data_42.json | 1 - .../json_schema_test_suite/type/data_43.json | 1 - .../json_schema_test_suite/type/data_44.json | 1 - .../json_schema_test_suite/type/data_45.json | 1 - .../json_schema_test_suite/type/data_46.json | 1 - .../json_schema_test_suite/type/data_50.json | 1 - .../json_schema_test_suite/type/data_51.json | 1 - .../json_schema_test_suite/type/data_52.json | 1 - .../json_schema_test_suite/type/data_53.json | 1 - .../json_schema_test_suite/type/data_54.json | 1 - .../json_schema_test_suite/type/data_55.json | 1 - .../json_schema_test_suite/type/data_56.json | 1 - .../json_schema_test_suite/type/data_60.json | 1 - .../json_schema_test_suite/type/data_61.json | 1 - .../json_schema_test_suite/type/data_62.json | 1 - .../json_schema_test_suite/type/data_63.json | 1 - .../json_schema_test_suite/type/data_64.json | 1 - .../json_schema_test_suite/type/data_65.json | 1 - .../json_schema_test_suite/type/data_66.json | 1 - .../json_schema_test_suite/type/data_70.json | 1 - .../json_schema_test_suite/type/data_71.json | 1 - .../json_schema_test_suite/type/data_72.json | 1 - .../json_schema_test_suite/type/data_73.json | 1 - .../json_schema_test_suite/type/data_74.json | 1 - .../json_schema_test_suite/type/data_75.json | 1 - .../json_schema_test_suite/type/data_76.json | 1 - .../json_schema_test_suite/type/schema_0.json | 1 - .../json_schema_test_suite/type/schema_1.json | 1 - .../json_schema_test_suite/type/schema_2.json | 1 - .../json_schema_test_suite/type/schema_3.json | 1 - .../json_schema_test_suite/type/schema_4.json | 1 - .../json_schema_test_suite/type/schema_5.json | 1 - .../json_schema_test_suite/type/schema_6.json | 1 - .../json_schema_test_suite/type/schema_7.json | 1 - .../uniqueItems/data_00.json | 1 - .../uniqueItems/data_01.json | 1 - .../uniqueItems/data_010.json | 1 - .../uniqueItems/data_011.json | 1 - .../uniqueItems/data_012.json | 1 - .../uniqueItems/data_02.json | 1 - .../uniqueItems/data_03.json | 1 - .../uniqueItems/data_04.json | 1 - .../uniqueItems/data_05.json | 1 - .../uniqueItems/data_06.json | 1 - .../uniqueItems/data_07.json | 1 - .../uniqueItems/data_08.json | 1 - .../uniqueItems/data_09.json | 1 - .../uniqueItems/schema_0.json | 1 - .../xeipuuv/gojsonschema/jsonschema_test.go | 131 + .../xeipuuv/gojsonschema/locales.go | 27 + .../github.com/xeipuuv/gojsonschema/result.go | 43 +- .../github.com/xeipuuv/gojsonschema/schema.go | 317 +- .../xeipuuv/gojsonschema/schemaPool.go | 127 +- .../xeipuuv/gojsonschema/schema_test.go | 553 +- .../xeipuuv/gojsonschema/subSchema.go | 58 +- .../testdata/draft4/additionalItems.json | 87 + .../testdata/draft4/additionalProperties.json | 98 + .../gojsonschema/testdata/draft4/allOf.json | 112 + .../gojsonschema/testdata/draft4/anyOf.json | 109 + .../gojsonschema/testdata/draft4/default.json | 49 + .../testdata/draft4/definitions.json | 32 + .../testdata/draft4/dependencies.json | 123 + .../gojsonschema/testdata/draft4/enum.json | 72 + .../gojsonschema/testdata/draft4/items.json | 78 + .../testdata/draft4/maxItems.json | 28 + .../testdata/draft4/maxLength.json | 33 + .../testdata/draft4/maxProperties.json | 38 + .../gojsonschema/testdata/draft4/maximum.json | 47 + .../testdata/draft4/minItems.json | 28 + .../testdata/draft4/minLength.json | 33 + .../testdata/draft4/minProperties.json | 38 + .../gojsonschema/testdata/draft4/minimum.json | 47 + .../testdata/draft4/multipleOf.json | 60 + .../gojsonschema/testdata/draft4/not.json | 96 + .../gojsonschema/testdata/draft4/oneOf.json | 109 + .../testdata/draft4/optional/bignum.json | 107 + .../draft4/optional/ecmascript-regex.json | 13 + .../testdata/draft4/optional/format.json | 223 + .../draft4/optional/zeroTerminatedFloats.json | 15 + .../gojsonschema/testdata/draft4/pattern.json | 34 + .../testdata/draft4/patternProperties.json | 120 + .../testdata/draft4/properties.json | 97 + .../gojsonschema/testdata/draft4/ref.json | 300 + .../testdata/draft4/refRemote.json | 171 + .../testdata/draft4/required.json | 54 + .../gojsonschema/testdata/draft4/type.json | 345 + .../testdata/draft4/uniqueItems.json | 79 + .../testdata/draft6/additionalItems.json | 87 + .../testdata/draft6/additionalProperties.json | 98 + .../gojsonschema/testdata/draft6/allOf.json | 145 + .../gojsonschema/testdata/draft6/anyOf.json | 142 + .../testdata/draft6/boolean_schema.json | 104 + .../gojsonschema/testdata/draft6/const.json | 86 + .../testdata/draft6/contains.json | 95 + .../gojsonschema/testdata/draft6/default.json | 49 + .../testdata/draft6/definitions.json | 32 + .../testdata/draft6/dependencies.json | 172 + .../gojsonschema/testdata/draft6/enum.json | 72 + .../testdata/draft6/exclusiveMaximum.json | 30 + .../testdata/draft6/exclusiveMinimum.json | 30 + .../gojsonschema/testdata/draft6/items.json | 133 + .../testdata/draft6/maxItems.json | 28 + .../testdata/draft6/maxLength.json | 33 + .../testdata/draft6/maxProperties.json | 38 + .../gojsonschema/testdata/draft6/maximum.json | 28 + .../testdata/draft6/minItems.json | 28 + .../testdata/draft6/minLength.json | 33 + .../testdata/draft6/minProperties.json | 38 + .../gojsonschema/testdata/draft6/minimum.json | 28 + .../testdata/draft6/multipleOf.json | 60 + .../gojsonschema/testdata/draft6/not.json | 117 + .../gojsonschema/testdata/draft6/oneOf.json | 153 + .../testdata/draft6/optional/bignum.json | 105 + .../draft6/optional/ecmascript-regex.json | 13 + .../testdata/draft6/optional/format.json | 458 + .../draft6/optional/zeroTerminatedFloats.json | 15 + .../gojsonschema/testdata/draft6/pattern.json | 34 + .../testdata/draft6/patternProperties.json | 151 + .../testdata/draft6/properties.json | 128 + .../testdata/draft6/propertyNames.json | 78 + .../gojsonschema/testdata/draft6/ref.json | 332 + .../testdata/draft6/refRemote.json | 171 + .../testdata/draft6/required.json | 70 + .../gojsonschema/testdata/draft6/type.json | 345 + .../testdata/draft6/uniqueItems.json | 79 + .../testdata/draft7/additionalItems.json | 87 + .../testdata/draft7/additionalProperties.json | 98 + .../gojsonschema/testdata/draft7/allOf.json | 145 + .../gojsonschema/testdata/draft7/anyOf.json | 142 + .../testdata/draft7/boolean_schema.json | 104 + .../gojsonschema/testdata/draft7/const.json | 86 + .../testdata/draft7/contains.json | 95 + .../gojsonschema/testdata/draft7/default.json | 49 + .../testdata/draft7/definitions.json | 32 + .../testdata/draft7/dependencies.json | 172 + .../gojsonschema/testdata/draft7/enum.json | 72 + .../testdata/draft7/exclusiveMaximum.json | 30 + .../testdata/draft7/exclusiveMinimum.json | 30 + .../testdata/draft7/if-then-else.json | 188 + .../gojsonschema/testdata/draft7/items.json | 133 + .../testdata/draft7/maxItems.json | 28 + .../testdata/draft7/maxLength.json | 33 + .../testdata/draft7/maxProperties.json | 38 + .../gojsonschema/testdata/draft7/maximum.json | 28 + .../testdata/draft7/minItems.json | 28 + .../testdata/draft7/minLength.json | 33 + .../testdata/draft7/minProperties.json | 38 + .../gojsonschema/testdata/draft7/minimum.json | 28 + .../testdata/draft7/multipleOf.json | 60 + .../gojsonschema/testdata/draft7/not.json | 117 + .../gojsonschema/testdata/draft7/oneOf.json | 153 + .../testdata/draft7/optional/bignum.json | 105 + .../testdata/draft7/optional/content.json | 62 + .../draft7/optional/ecmascript-regex.json | 13 + .../draft7/optional/format/date-time.json | 23 + .../testdata/draft7/optional/format/date.json | 23 + .../draft7/optional/format/email.json | 18 + .../draft7/optional/format/hostname.json | 33 + .../draft7/optional/format/idn-email.json | 18 + .../draft7/optional/format/idn-hostname.json | 28 + .../testdata/draft7/optional/format/ipv4.json | 33 + .../testdata/draft7/optional/format/ipv6.json | 28 + .../draft7/optional/format/iri-reference.json | 43 + .../testdata/draft7/optional/format/iri.json | 48 + .../draft7/optional/format/json-pointer.json | 168 + .../draft7/optional/format/regex.json | 18 + .../format/relative-json-pointer.json | 33 + .../testdata/draft7/optional/format/time.json | 23 + .../draft7/optional/format/uri-reference.json | 43 + .../draft7/optional/format/uri-template.json | 30 + .../testdata/draft7/optional/format/uri.json | 103 + .../draft7/optional/zeroTerminatedFloats.json | 15 + .../gojsonschema/testdata/draft7/pattern.json | 34 + .../testdata/draft7/patternProperties.json | 151 + .../testdata/draft7/properties.json | 128 + .../testdata/draft7/propertyNames.json | 78 + .../gojsonschema/testdata/draft7/ref.json | 332 + .../testdata/draft7/refRemote.json | 171 + .../testdata/draft7/required.json | 70 + .../gojsonschema/testdata/draft7/type.json | 345 + .../testdata/draft7/uniqueItems.json | 79 + .../extra/fragment_schema.json} | 0 .../remotes}/folder/folderInteger.json | 0 .../remotes}/integer.json | 0 .../gojsonschema/testdata/remotes/name.json | 11 + .../remotes}/subSchemas.json | 0 .../github.com/xeipuuv/gojsonschema/utils.go | 62 +- .../xeipuuv/gojsonschema/utils_test.go | 27 + .../xeipuuv/gojsonschema/validation.go | 224 +- vendor/github.com/yalp/jsonpath/.travis.yml | 3 + vendor/github.com/yalp/jsonpath/LICENSE | 29 + vendor/github.com/yalp/jsonpath/README.md | 5 + vendor/github.com/yalp/jsonpath/jsonpath.go | 116 +- .../github.com/yalp/jsonpath/jsonpath_test.go | 178 +- vendor/golang.org/x/crypto/CONTRIBUTING.md | 15 +- vendor/golang.org/x/crypto/acme/acme.go | 434 +- vendor/golang.org/x/crypto/acme/acme_test.go | 309 +- .../x/crypto/acme/autocert/autocert.go | 370 +- .../x/crypto/acme/autocert/autocert_test.go | 624 +- .../x/crypto/acme/autocert/cache.go | 6 +- .../x/crypto/acme/autocert/example_test.go | 4 +- .../acme/autocert/internal/acmetest/ca.go | 416 + .../x/crypto/acme/autocert/listener.go | 7 +- .../x/crypto/acme/autocert/renewal.go | 45 +- .../x/crypto/acme/autocert/renewal_test.go | 178 +- vendor/golang.org/x/crypto/acme/http.go | 281 + vendor/golang.org/x/crypto/acme/http_test.go | 209 + vendor/golang.org/x/crypto/acme/types.go | 8 +- vendor/golang.org/x/crypto/argon2/argon2.go | 81 +- .../x/crypto/argon2/blamka_amd64.go | 9 +- .../golang.org/x/crypto/argon2/blamka_amd64.s | 9 - vendor/golang.org/x/crypto/blake2b/blake2b.go | 68 + .../x/crypto/blake2b/blake2bAVX2_amd64.go | 26 +- .../x/crypto/blake2b/blake2bAVX2_amd64.s | 12 - .../x/crypto/blake2b/blake2b_amd64.go | 9 +- .../x/crypto/blake2b/blake2b_amd64.s | 9 - .../x/crypto/blake2b/blake2b_test.go | 49 + vendor/golang.org/x/crypto/blake2s/blake2s.go | 57 + .../x/crypto/blake2s/blake2s_386.go | 19 +- .../golang.org/x/crypto/blake2s/blake2s_386.s | 25 - .../x/crypto/blake2s/blake2s_amd64.go | 23 +- .../x/crypto/blake2s/blake2s_amd64.s | 25 - .../x/crypto/blake2s/blake2s_test.go | 48 + vendor/golang.org/x/crypto/bn256/bn256.go | 20 +- vendor/golang.org/x/crypto/bn256/curve.go | 9 + vendor/golang.org/x/crypto/bn256/twist.go | 9 + .../chacha20poly1305/chacha20poly1305.go | 28 +- .../chacha20poly1305_amd64.go | 86 +- .../chacha20poly1305/chacha20poly1305_amd64.s | 19 - .../chacha20poly1305_generic.go | 37 +- .../chacha20poly1305/chacha20poly1305_test.go | 223 +- .../chacha20poly1305_vectors_test.go | 394 + .../chacha20poly1305/xchacha20poly1305.go | 104 + vendor/golang.org/x/crypto/cryptobyte/asn1.go | 67 +- .../x/crypto/cryptobyte/asn1_test.go | 33 + .../golang.org/x/crypto/cryptobyte/string.go | 29 +- vendor/golang.org/x/crypto/ed25519/ed25519.go | 60 +- .../x/crypto/ed25519/ed25519_test.go | 37 + .../internal/edwards25519/edwards25519.go | 22 + .../internal/chacha20/chacha_generic.go | 420 +- .../crypto/internal/chacha20/chacha_noasm.go | 16 + .../crypto/internal/chacha20/chacha_s390x.go | 30 + .../x/crypto/internal/chacha20/chacha_s390x.s | 283 + .../x/crypto/internal/chacha20/chacha_test.go | 192 + .../crypto/internal/chacha20/vectors_test.go | 578 + .../x/crypto/internal/chacha20/xor.go | 43 + .../x/crypto/internal/subtle/aliasing.go | 32 + .../internal/subtle/aliasing_appengine.go | 35 + .../x/crypto/internal/subtle/aliasing_test.go | 50 + .../x/crypto/nacl/secretbox/secretbox.go | 9 +- vendor/golang.org/x/crypto/nacl/sign/sign.go | 90 + .../x/crypto/nacl/sign/sign_test.go | 74 + vendor/golang.org/x/crypto/ocsp/ocsp.go | 11 +- vendor/golang.org/x/crypto/openpgp/keys.go | 40 +- .../golang.org/x/crypto/openpgp/keys_test.go | 138 +- .../x/crypto/openpgp/packet/encrypted_key.go | 9 +- .../openpgp/packet/encrypted_key_test.go | 63 +- .../x/crypto/openpgp/packet/packet.go | 32 +- .../x/crypto/openpgp/packet/public_key.go | 11 +- .../crypto/openpgp/packet/public_key_test.go | 26 + .../golang.org/x/crypto/openpgp/read_test.go | 2 +- vendor/golang.org/x/crypto/openpgp/write.go | 174 +- .../golang.org/x/crypto/openpgp/write_test.go | 89 + .../x/crypto/poly1305/poly1305_test.go | 113 +- .../golang.org/x/crypto/poly1305/sum_noasm.go | 14 + .../golang.org/x/crypto/poly1305/sum_ref.go | 10 +- .../golang.org/x/crypto/poly1305/sum_s390x.go | 49 + .../golang.org/x/crypto/poly1305/sum_s390x.s | 400 + .../x/crypto/poly1305/sum_vmsl_s390x.s | 931 + .../x/crypto/poly1305/vectors_test.go | 2943 +++ .../x/crypto/ripemd160/ripemd160_test.go | 18 +- .../x/crypto/ripemd160/ripemd160block.go | 64 +- vendor/golang.org/x/crypto/salsa20/salsa20.go | 6 +- vendor/golang.org/x/crypto/scrypt/scrypt.go | 2 +- vendor/golang.org/x/crypto/sha3/hashes.go | 34 +- .../x/crypto/sha3/hashes_generic.go | 27 + vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 289 + vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 49 + vendor/golang.org/x/crypto/sha3/sha3_test.go | 44 +- vendor/golang.org/x/crypto/sha3/shake.go | 16 +- .../golang.org/x/crypto/sha3/shake_generic.go | 19 + .../golang.org/x/crypto/ssh/agent/client.go | 2 +- .../golang.org/x/crypto/ssh/agent/keyring.go | 2 +- vendor/golang.org/x/crypto/ssh/certs.go | 4 +- vendor/golang.org/x/crypto/ssh/cipher.go | 155 +- vendor/golang.org/x/crypto/ssh/cipher_test.go | 11 +- vendor/golang.org/x/crypto/ssh/client.go | 4 +- vendor/golang.org/x/crypto/ssh/client_auth.go | 95 +- .../x/crypto/ssh/client_auth_test.go | 4 +- vendor/golang.org/x/crypto/ssh/common.go | 15 +- vendor/golang.org/x/crypto/ssh/keys.go | 8 +- vendor/golang.org/x/crypto/ssh/keys_test.go | 24 +- .../x/crypto/ssh/knownhosts/knownhosts.go | 58 +- .../crypto/ssh/knownhosts/knownhosts_test.go | 29 +- vendor/golang.org/x/crypto/ssh/mux_test.go | 4 - vendor/golang.org/x/crypto/ssh/server.go | 21 +- vendor/golang.org/x/crypto/ssh/streamlocal.go | 1 + vendor/golang.org/x/crypto/ssh/tcpip.go | 9 + .../x/crypto/ssh/terminal/terminal_test.go | 8 + .../golang.org/x/crypto/ssh/terminal/util.go | 4 +- .../x/crypto/ssh/terminal/util_solaris.go | 36 +- .../x/crypto/ssh/terminal/util_windows.go | 14 +- .../x/crypto/ssh/test/multi_auth_test.go | 144 + .../x/crypto/ssh/test/session_test.go | 61 +- .../x/crypto/ssh/test/sshd_test_pw.c | 173 + .../x/crypto/ssh/test/test_unix_test.go | 80 +- .../golang.org/x/crypto/ssh/testdata/keys.go | 29 + vendor/golang.org/x/crypto/ssh/transport.go | 47 +- vendor/golang.org/x/crypto/xtea/block.go | 2 +- vendor/golang.org/x/crypto/xtea/cipher.go | 4 +- vendor/golang.org/x/crypto/xts/xts.go | 8 + vendor/golang.org/x/net/CONTRIBUTING.md | 15 +- vendor/golang.org/x/net/bpf/instructions.go | 32 +- .../x/net/dns/dnsmessage/example_test.go | 8 +- .../x/net/dns/dnsmessage/message.go | 845 +- .../x/net/dns/dnsmessage/message_test.go | 944 +- vendor/golang.org/x/net/html/atom/gen.go | 5 +- vendor/golang.org/x/net/html/atom/table.go | 1444 +- .../golang.org/x/net/html/atom/table_test.go | 3 + vendor/golang.org/x/net/html/const.go | 2 +- vendor/golang.org/x/net/html/entity.go | 4154 ++-- vendor/golang.org/x/net/html/foreign.go | 6 +- vendor/golang.org/x/net/html/node.go | 33 +- vendor/golang.org/x/net/html/parse.go | 370 +- vendor/golang.org/x/net/html/parse_test.go | 54 +- .../x/net/html/testdata/go/template.dat | 13 + .../x/net/html/testdata/webkit/ruby.dat | 298 + .../x/net/html/testdata/webkit/template.dat | 1117 + vendor/golang.org/x/net/html/token_test.go | 28 +- vendor/golang.org/x/net/http/httpguts/guts.go | 50 + .../{lex/httplex => http/httpguts}/httplex.go | 7 +- .../httplex => http/httpguts}/httplex_test.go | 2 +- .../x/net/http/httpproxy/export_test.go | 8 +- .../golang.org/x/net/http/httpproxy/proxy.go | 229 +- .../x/net/http/httpproxy/proxy_test.go | 70 +- vendor/golang.org/x/net/http2/ciphers.go | 2 +- .../x/net/http2/client_conn_pool.go | 28 +- .../x/net/http2/configure_transport.go | 8 +- vendor/golang.org/x/net/http2/flow.go | 10 +- vendor/golang.org/x/net/http2/flow_test.go | 34 + vendor/golang.org/x/net/http2/frame.go | 67 +- vendor/golang.org/x/net/http2/frame_test.go | 44 + vendor/golang.org/x/net/http2/go111.go | 26 + vendor/golang.org/x/net/http2/go17.go | 15 + vendor/golang.org/x/net/http2/h2c/h2c.go | 492 + vendor/golang.org/x/net/http2/h2c/h2c_test.go | 58 + .../golang.org/x/net/http2/h2demo/.gitignore | 1 + .../golang.org/x/net/http2/h2demo/Dockerfile | 11 + .../x/net/http2/h2demo/Dockerfile.0 | 134 + vendor/golang.org/x/net/http2/h2demo/Makefile | 59 +- .../x/net/http2/h2demo/deployment-prod.yaml | 28 + .../golang.org/x/net/http2/h2demo/h2demo.go | 36 +- .../x/net/http2/h2demo/service.yaml | 17 + vendor/golang.org/x/net/http2/h2i/h2i.go | 2 +- vendor/golang.org/x/net/http2/hpack/encode.go | 2 +- vendor/golang.org/x/net/http2/hpack/hpack.go | 6 + .../x/net/http2/hpack/hpack_test.go | 40 + .../golang.org/x/net/http2/hpack/huffman.go | 20 +- vendor/golang.org/x/net/http2/http2.go | 8 +- vendor/golang.org/x/net/http2/http2_test.go | 28 + vendor/golang.org/x/net/http2/not_go111.go | 17 + vendor/golang.org/x/net/http2/not_go17.go | 8 + vendor/golang.org/x/net/http2/server.go | 85 +- vendor/golang.org/x/net/http2/server_test.go | 147 +- vendor/golang.org/x/net/http2/transport.go | 226 +- .../golang.org/x/net/http2/transport_test.go | 358 +- vendor/golang.org/x/net/http2/write.go | 4 +- vendor/golang.org/x/net/icmp/diag_test.go | 274 + vendor/golang.org/x/net/icmp/dstunreach.go | 8 +- vendor/golang.org/x/net/icmp/echo.go | 114 +- vendor/golang.org/x/net/icmp/endpoint.go | 18 +- vendor/golang.org/x/net/icmp/extension.go | 49 +- .../golang.org/x/net/icmp/extension_test.go | 530 +- vendor/golang.org/x/net/icmp/interface.go | 100 +- vendor/golang.org/x/net/icmp/ipv4.go | 12 +- vendor/golang.org/x/net/icmp/ipv4_test.go | 118 +- vendor/golang.org/x/net/icmp/listen_stub.go | 2 +- vendor/golang.org/x/net/icmp/message.go | 29 +- vendor/golang.org/x/net/icmp/message_test.go | 245 +- vendor/golang.org/x/net/icmp/messagebody.go | 6 +- vendor/golang.org/x/net/icmp/mpls.go | 4 +- vendor/golang.org/x/net/icmp/multipart.go | 38 +- .../golang.org/x/net/icmp/multipart_test.go | 867 +- vendor/golang.org/x/net/icmp/packettoobig.go | 2 +- vendor/golang.org/x/net/icmp/paramprob.go | 8 +- vendor/golang.org/x/net/icmp/ping_test.go | 200 - vendor/golang.org/x/net/icmp/timeexceeded.go | 8 +- .../golang.org/x/net/internal/iana/const.go | 109 +- vendor/golang.org/x/net/internal/iana/gen.go | 284 +- .../x/net/internal/nettest/helper_stub.go | 2 +- .../x/net/internal/nettest/stack.go | 4 +- .../x/net/internal/socket/zsys_netbsd_arm.go | 6 + .../golang.org/x/net/internal/socks/client.go | 168 + .../x/net/internal/socks/dial_test.go | 170 + .../golang.org/x/net/internal/socks/socks.go | 316 + .../x/net/internal/sockstest/server.go | 241 + .../x/net/internal/sockstest/server_test.go | 103 + vendor/golang.org/x/net/ipv4/batch.go | 9 +- vendor/golang.org/x/net/ipv4/dgramopt.go | 31 +- vendor/golang.org/x/net/ipv4/doc.go | 4 +- vendor/golang.org/x/net/ipv4/endpoint.go | 21 +- vendor/golang.org/x/net/ipv4/gen.go | 4 +- vendor/golang.org/x/net/ipv4/genericopt.go | 10 +- vendor/golang.org/x/net/ipv4/header.go | 17 +- vendor/golang.org/x/net/ipv4/helper.go | 1 + vendor/golang.org/x/net/ipv4/iana.go | 10 +- .../golang.org/x/net/ipv4/multicast_test.go | 4 +- .../x/net/ipv4/multicastlistener_test.go | 10 +- .../x/net/ipv4/multicastsockopt_test.go | 4 +- vendor/golang.org/x/net/ipv4/packet.go | 5 +- vendor/golang.org/x/net/ipv4/payload_cmsg.go | 11 +- .../x/net/ipv4/payload_cmsg_go1_8.go | 2 +- .../x/net/ipv4/payload_cmsg_go1_9.go | 2 +- .../golang.org/x/net/ipv4/payload_nocmsg.go | 11 +- .../x/net/ipv4/readwrite_go1_8_test.go | 4 +- .../x/net/ipv4/readwrite_go1_9_test.go | 4 +- .../golang.org/x/net/ipv4/readwrite_test.go | 2 +- vendor/golang.org/x/net/ipv4/unicast_test.go | 6 +- .../x/net/ipv4/unicastsockopt_test.go | 6 +- vendor/golang.org/x/net/ipv6/batch.go | 5 +- vendor/golang.org/x/net/ipv6/dgramopt.go | 35 +- vendor/golang.org/x/net/ipv6/doc.go | 4 +- vendor/golang.org/x/net/ipv6/endpoint.go | 13 +- vendor/golang.org/x/net/ipv6/gen.go | 4 +- vendor/golang.org/x/net/ipv6/genericopt.go | 10 +- vendor/golang.org/x/net/ipv6/helper.go | 1 + vendor/golang.org/x/net/ipv6/iana.go | 10 +- vendor/golang.org/x/net/ipv6/icmp_test.go | 4 +- .../golang.org/x/net/ipv6/multicast_test.go | 4 +- .../x/net/ipv6/multicastlistener_test.go | 10 +- .../x/net/ipv6/multicastsockopt_test.go | 2 +- vendor/golang.org/x/net/ipv6/payload_cmsg.go | 11 +- .../x/net/ipv6/payload_cmsg_go1_8.go | 2 +- .../x/net/ipv6/payload_cmsg_go1_9.go | 2 +- .../golang.org/x/net/ipv6/payload_nocmsg.go | 11 +- .../x/net/ipv6/readwrite_go1_8_test.go | 4 +- .../x/net/ipv6/readwrite_go1_9_test.go | 4 +- .../golang.org/x/net/ipv6/readwrite_test.go | 2 +- vendor/golang.org/x/net/ipv6/sockopt_test.go | 6 +- vendor/golang.org/x/net/ipv6/unicast_test.go | 4 +- .../x/net/ipv6/unicastsockopt_test.go | 4 +- vendor/golang.org/x/net/netutil/listen.go | 36 +- .../golang.org/x/net/netutil/listen_test.go | 46 + vendor/golang.org/x/net/proxy/proxy_test.go | 132 +- vendor/golang.org/x/net/proxy/socks5.go | 222 +- vendor/golang.org/x/net/publicsuffix/list.go | 39 +- vendor/golang.org/x/net/publicsuffix/table.go | 18985 ++++++++-------- .../x/net/publicsuffix/table_test.go | 632 +- vendor/golang.org/x/net/route/syscall.go | 2 +- vendor/golang.org/x/net/trace/trace.go | 67 +- vendor/golang.org/x/net/webdav/prop.go | 54 +- vendor/golang.org/x/net/webdav/prop_test.go | 106 +- .../golang.org/x/net/websocket/websocket.go | 3 + vendor/golang.org/x/sys/CONTRIBUTING.md | 15 +- vendor/golang.org/x/sys/cpu/cpu.go | 38 + vendor/golang.org/x/sys/cpu/cpu_arm.go | 7 + vendor/golang.org/x/sys/cpu/cpu_arm64.go | 7 + vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 16 + vendor/golang.org/x/sys/cpu/cpu_gccgo.c | 43 + vendor/golang.org/x/sys/cpu/cpu_gccgo.go | 26 + vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 9 + vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 9 + vendor/golang.org/x/sys/cpu/cpu_ppc64x.go | 9 + vendor/golang.org/x/sys/cpu/cpu_s390x.go | 7 + vendor/golang.org/x/sys/cpu/cpu_test.go | 28 + vendor/golang.org/x/sys/cpu/cpu_x86.go | 55 + vendor/golang.org/x/sys/cpu/cpu_x86.s | 27 + vendor/golang.org/x/sys/plan9/asm_plan9_arm.s | 25 + vendor/golang.org/x/sys/plan9/mkerrors.sh | 2 +- vendor/golang.org/x/sys/plan9/mksyscall.pl | 2 +- vendor/golang.org/x/sys/plan9/syscall.go | 3 + .../golang.org/x/sys/plan9/syscall_plan9.go | 10 +- .../x/sys/plan9/zsyscall_plan9_386.go | 2 +- .../x/sys/plan9/zsyscall_plan9_amd64.go | 2 +- .../x/sys/plan9/zsyscall_plan9_arm.go | 284 + .../golang.org/x/sys/unix/affinity_linux.go | 2 +- vendor/golang.org/x/sys/unix/aliases.go | 14 + .../x/sys/unix/asm_dragonfly_amd64.s | 10 +- vendor/golang.org/x/sys/unix/cap_freebsd.go | 30 +- vendor/golang.org/x/sys/unix/creds_test.go | 18 - .../golang.org/x/sys/unix/dev_darwin_test.go | 51 - .../x/sys/unix/dev_dragonfly_test.go | 50 - .../golang.org/x/sys/unix/dev_linux_test.go | 3 + .../golang.org/x/sys/unix/dev_netbsd_test.go | 50 - .../golang.org/x/sys/unix/dev_openbsd_test.go | 54 - .../golang.org/x/sys/unix/dev_solaris_test.go | 51 - vendor/golang.org/x/sys/unix/example_test.go | 19 + .../x/sys/unix/{flock.go => fcntl.go} | 10 + ...ck_linux_32bit.go => fcntl_linux_32bit.go} | 0 vendor/golang.org/x/sys/unix/gccgo_c.c | 9 - vendor/golang.org/x/sys/unix/ioctl.go | 30 + vendor/golang.org/x/sys/unix/linux/Dockerfile | 37 +- vendor/golang.org/x/sys/unix/linux/mkall.go | 270 +- vendor/golang.org/x/sys/unix/linux/types.go | 1106 +- vendor/golang.org/x/sys/unix/mkerrors.sh | 67 +- vendor/golang.org/x/sys/unix/mkpost.go | 19 +- vendor/golang.org/x/sys/unix/mksyscall.pl | 15 +- .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 2 +- .../golang.org/x/sys/unix/openbsd_pledge.go | 4 +- vendor/golang.org/x/sys/unix/syscall.go | 11 +- vendor/golang.org/x/sys/unix/syscall_bsd.go | 49 +- .../golang.org/x/sys/unix/syscall_darwin.go | 128 +- .../x/sys/unix/syscall_darwin_test.go | 19 + .../x/sys/unix/syscall_dragonfly.go | 9 +- .../golang.org/x/sys/unix/syscall_freebsd.go | 246 +- .../x/sys/unix/syscall_freebsd_test.go | 15 + vendor/golang.org/x/sys/unix/syscall_linux.go | 285 +- .../x/sys/unix/syscall_linux_386.go | 16 +- .../x/sys/unix/syscall_linux_amd64.go | 22 +- .../x/sys/unix/syscall_linux_arm.go | 10 +- .../x/sys/unix/syscall_linux_arm64.go | 62 +- .../golang.org/x/sys/unix/syscall_linux_gc.go | 14 + .../x/sys/unix/syscall_linux_gc_386.go | 16 + .../x/sys/unix/syscall_linux_gccgo_386.go | 30 + .../x/sys/unix/syscall_linux_gccgo_arm.go | 20 + .../x/sys/unix/syscall_linux_mips64x.go | 12 +- .../x/sys/unix/syscall_linux_mipsx.go | 20 +- .../x/sys/unix/syscall_linux_ppc64x.go | 8 +- .../x/sys/unix/syscall_linux_s390x.go | 4 + .../x/sys/unix/syscall_linux_sparc64.go | 3 + .../x/sys/unix/syscall_linux_test.go | 234 +- .../golang.org/x/sys/unix/syscall_netbsd.go | 22 +- .../x/sys/unix/syscall_netbsd_test.go | 20 + .../golang.org/x/sys/unix/syscall_openbsd.go | 12 +- .../x/sys/unix/syscall_openbsd_amd64.go | 4 + .../golang.org/x/sys/unix/syscall_solaris.go | 28 +- .../x/sys/unix/syscall_solaris_amd64.go | 5 - vendor/golang.org/x/sys/unix/syscall_unix.go | 110 +- .../x/sys/unix/syscall_unix_test.go | 213 +- vendor/golang.org/x/sys/unix/types_freebsd.go | 2 + vendor/golang.org/x/sys/unix/types_netbsd.go | 11 + vendor/golang.org/x/sys/unix/types_openbsd.go | 17 - vendor/golang.org/x/sys/unix/xattr_bsd.go | 231 + vendor/golang.org/x/sys/unix/xattr_test.go | 201 + .../x/sys/unix/zerrors_darwin_386.go | 292 +- .../x/sys/unix/zerrors_darwin_amd64.go | 292 +- .../x/sys/unix/zerrors_darwin_arm.go | 292 +- .../x/sys/unix/zerrors_darwin_arm64.go | 292 +- .../x/sys/unix/zerrors_dragonfly_amd64.go | 281 +- .../x/sys/unix/zerrors_freebsd_386.go | 270 +- .../x/sys/unix/zerrors_freebsd_amd64.go | 270 +- .../x/sys/unix/zerrors_freebsd_arm.go | 270 +- .../x/sys/unix/zerrors_linux_386.go | 673 +- .../x/sys/unix/zerrors_linux_amd64.go | 672 +- .../x/sys/unix/zerrors_linux_arm.go | 674 +- .../x/sys/unix/zerrors_linux_arm64.go | 673 +- .../x/sys/unix/zerrors_linux_mips.go | 677 +- .../x/sys/unix/zerrors_linux_mips64.go | 677 +- .../x/sys/unix/zerrors_linux_mips64le.go | 677 +- .../x/sys/unix/zerrors_linux_mipsle.go | 677 +- .../x/sys/unix/zerrors_linux_ppc64.go | 673 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 673 +- .../x/sys/unix/zerrors_linux_s390x.go | 671 +- .../x/sys/unix/zerrors_linux_sparc64.go | 2 +- .../x/sys/unix/zerrors_netbsd_386.go | 273 +- .../x/sys/unix/zerrors_netbsd_amd64.go | 273 +- .../x/sys/unix/zerrors_netbsd_arm.go | 273 +- .../x/sys/unix/zerrors_openbsd_386.go | 287 +- .../x/sys/unix/zerrors_openbsd_amd64.go | 533 +- .../x/sys/unix/zerrors_openbsd_arm.go | 287 +- .../x/sys/unix/zerrors_solaris_amd64.go | 336 +- .../x/sys/unix/zsyscall_darwin_386.go | 149 + .../x/sys/unix/zsyscall_darwin_amd64.go | 149 + .../x/sys/unix/zsyscall_darwin_arm.go | 151 +- .../x/sys/unix/zsyscall_darwin_arm64.go | 149 + .../x/sys/unix/zsyscall_dragonfly_amd64.go | 30 + .../x/sys/unix/zsyscall_freebsd_386.go | 15 + .../x/sys/unix/zsyscall_freebsd_amd64.go | 15 + .../x/sys/unix/zsyscall_freebsd_arm.go | 15 + .../x/sys/unix/zsyscall_linux_386.go | 267 +- .../x/sys/unix/zsyscall_linux_amd64.go | 259 +- .../x/sys/unix/zsyscall_linux_arm.go | 269 +- .../x/sys/unix/zsyscall_linux_arm64.go | 192 +- .../x/sys/unix/zsyscall_linux_mips.go | 325 +- .../x/sys/unix/zsyscall_linux_mips64.go | 243 +- .../x/sys/unix/zsyscall_linux_mips64le.go | 243 +- .../x/sys/unix/zsyscall_linux_mipsle.go | 325 +- .../x/sys/unix/zsyscall_linux_ppc64.go | 247 +- .../x/sys/unix/zsyscall_linux_ppc64le.go | 247 +- .../x/sys/unix/zsyscall_linux_s390x.go | 233 +- .../x/sys/unix/zsyscall_linux_sparc64.go | 501 +- .../x/sys/unix/zsyscall_netbsd_386.go | 269 + .../x/sys/unix/zsyscall_netbsd_amd64.go | 269 + .../x/sys/unix/zsyscall_netbsd_arm.go | 269 + .../x/sys/unix/zsyscall_openbsd_386.go | 66 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 66 + .../x/sys/unix/zsyscall_openbsd_arm.go | 66 + .../x/sys/unix/zsyscall_solaris_amd64.go | 44 + .../x/sys/unix/zsysctl_openbsd_386.go | 2 +- .../x/sys/unix/zsysctl_openbsd_amd64.go | 53 +- .../x/sys/unix/zsysctl_openbsd_arm.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc64.go | 3 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 3 + .../x/sys/unix/zsysnum_linux_s390x.go | 46 +- .../x/sys/unix/zsysnum_linux_sparc64.go | 2 +- .../x/sys/unix/zsysnum_netbsd_386.go | 2 +- .../x/sys/unix/zsysnum_netbsd_amd64.go | 2 +- .../x/sys/unix/zsysnum_netbsd_arm.go | 2 +- .../x/sys/unix/zsysnum_openbsd_386.go | 2 +- .../x/sys/unix/zsysnum_openbsd_amd64.go | 25 +- .../x/sys/unix/zsysnum_openbsd_arm.go | 2 +- .../x/sys/unix/ztypes_darwin_386.go | 112 +- .../x/sys/unix/ztypes_darwin_amd64.go | 158 +- .../x/sys/unix/ztypes_darwin_arm.go | 112 +- .../x/sys/unix/ztypes_darwin_arm64.go | 158 +- .../x/sys/unix/ztypes_dragonfly_amd64.go | 100 +- .../x/sys/unix/ztypes_freebsd_386.go | 2 + .../x/sys/unix/ztypes_freebsd_amd64.go | 2 + .../x/sys/unix/ztypes_freebsd_arm.go | 2 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 1339 +- .../x/sys/unix/ztypes_linux_amd64.go | 1349 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 1358 +- .../x/sys/unix/ztypes_linux_arm64.go | 1351 +- .../x/sys/unix/ztypes_linux_mips.go | 1322 +- .../x/sys/unix/ztypes_linux_mips64.go | 1347 +- .../x/sys/unix/ztypes_linux_mips64le.go | 1347 +- .../x/sys/unix/ztypes_linux_mipsle.go | 1322 +- .../x/sys/unix/ztypes_linux_ppc64.go | 1357 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 1357 +- .../x/sys/unix/ztypes_linux_s390x.go | 1251 +- .../x/sys/unix/ztypes_linux_sparc64.go | 208 +- .../x/sys/unix/ztypes_netbsd_386.go | 9 + .../x/sys/unix/ztypes_netbsd_amd64.go | 9 + .../x/sys/unix/ztypes_netbsd_arm.go | 9 + .../x/sys/unix/ztypes_openbsd_386.go | 17 - .../x/sys/unix/ztypes_openbsd_amd64.go | 108 +- .../x/sys/unix/ztypes_openbsd_arm.go | 17 - .../x/sys/unix/ztypes_solaris_amd64.go | 174 +- vendor/golang.org/x/sys/windows/aliases.go | 13 + .../x/sys/windows/asm_windows_386.s | 4 +- .../x/sys/windows/asm_windows_amd64.s | 2 +- .../golang.org/x/sys/windows/registry/key.go | 10 +- .../x/sys/windows/registry/registry_test.go | 2 +- .../sys/windows/registry/zsyscall_windows.go | 2 +- .../x/sys/windows/security_windows.go | 4 +- vendor/golang.org/x/sys/windows/service.go | 19 + .../x/sys/windows/svc/debug/service.go | 2 +- .../x/sys/windows/svc/example/service.go | 2 + .../x/sys/windows/svc/mgr/config.go | 40 +- .../x/sys/windows/svc/mgr/mgr_test.go | 113 + .../x/sys/windows/svc/mgr/recovery.go | 135 + .../golang.org/x/sys/windows/svc/service.go | 4 +- .../golang.org/x/sys/windows/svc/svc_test.go | 19 +- .../golang.org/x/sys/windows/svc/sys_amd64.s | 2 +- vendor/golang.org/x/sys/windows/syscall.go | 3 + .../x/sys/windows/syscall_windows.go | 2 + .../x/sys/windows/syscall_windows_test.go | 6 + .../golang.org/x/sys/windows/types_windows.go | 65 +- .../x/sys/windows/zsyscall_windows.go | 15 +- vendor/golang.org/x/text/cmd/gotext/common.go | 3 - .../cmd/gotext/examples/extract/catalog.go | 60 +- .../extract/locales/de/messages.gotext.json | 34 +- .../extract/locales/de/out.gotext.json | 113 +- .../locales/en-US/messages.gotext.json | 32 +- .../extract/locales/en-US/out.gotext.json | 134 +- .../extract/locales}/extracted.gotext.json | 68 +- .../extract/locales/zh/messages.gotext.json | 20 +- .../extract/locales/zh/out.gotext.json | 107 +- .../text/cmd/gotext/examples/extract/main.go | 3 +- .../examples/extract_http/catalog_gen.go | 57 - .../extract_http/locales/de/out.gotext.json | 8 +- .../locales/en-US/out.gotext.json | 8 +- .../out.gotext.json => extracted.gotext.json} | 22 +- .../extract_http/locales/zh/out.gotext.json | 16 +- .../cmd/gotext/examples/extract_http/main.go | 2 +- .../golang.org/x/text/cmd/gotext/extract.go | 59 +- .../golang.org/x/text/cmd/gotext/generate.go | 87 +- vendor/golang.org/x/text/cmd/gotext/main.go | 29 +- .../golang.org/x/text/cmd/gotext/rewrite.go | 2 +- vendor/golang.org/x/text/cmd/gotext/update.go | 52 - .../x/text/currency/example_test.go | 4 +- .../x/text/internal/catmsg/catmsg.go | 43 +- .../x/text/internal/catmsg/catmsg_test.go | 13 +- .../x/text/message/pipeline/extract.go | 25 +- .../x/text/message/pipeline/generate.go | 97 +- .../x/text/message/pipeline/go19_test.go | 13 - .../x/text/message/pipeline/message.go | 46 +- .../x/text/message/pipeline/pipeline.go | 371 +- .../x/text/message/pipeline/pipeline_test.go | 126 - .../x/text/message/pipeline/rewrite.go | 4 +- .../pipeline/testdata/test1/catalog_gen.go | 85 - .../testdata/test1/catalog_gen.go.want | 85 - .../pipeline/testdata/test1/catalog_test.go | 49 - .../testdata/test1/extracted.gotext.json.want | 188 - .../test1/locales/de/messages.gotext.json | 123 - .../testdata/test1/locales/de/out.gotext.json | 137 - .../test1/locales/de/out.gotext.json.want | 137 - .../test1/locales/en-US/messages.gotext.json | 91 - .../test1/locales/en-US/out.gotext.json | 154 - .../test1/locales/en-US/out.gotext.json.want | 154 - .../test1/locales/zh/messages.gotext.json | 135 - .../testdata/test1/locales/zh/out.gotext.json | 137 - .../test1/locales/zh/out.gotext.json.want | 137 - .../message/pipeline/testdata/test1/test1.go | 75 - 1771 files changed, 103836 insertions(+), 39300 deletions(-) create mode 100644 vendor/github.com/google/uuid/.travis.yml create mode 100644 vendor/github.com/google/uuid/CONTRIBUTING.md create mode 100644 vendor/github.com/google/uuid/CONTRIBUTORS rename vendor/github.com/{klauspost/crc32 => google/uuid}/LICENSE (94%) create mode 100644 vendor/github.com/google/uuid/README.md create mode 100644 vendor/github.com/google/uuid/dce.go create mode 100644 vendor/github.com/google/uuid/doc.go create mode 100644 vendor/github.com/google/uuid/hash.go create mode 100644 vendor/github.com/google/uuid/json_test.go create mode 100644 vendor/github.com/google/uuid/marshal.go create mode 100644 vendor/github.com/google/uuid/node.go create mode 100644 vendor/github.com/google/uuid/seq_test.go create mode 100644 vendor/github.com/google/uuid/sql.go create mode 100644 vendor/github.com/google/uuid/sql_test.go create mode 100644 vendor/github.com/google/uuid/time.go create mode 100644 vendor/github.com/google/uuid/util.go create mode 100644 vendor/github.com/google/uuid/uuid.go create mode 100644 vendor/github.com/google/uuid/uuid_test.go create mode 100644 vendor/github.com/google/uuid/version1.go create mode 100644 vendor/github.com/google/uuid/version4.go create mode 100644 vendor/github.com/klauspost/compress/.gitattributes create mode 100644 vendor/github.com/klauspost/compress/compressible.go create mode 100644 vendor/github.com/klauspost/compress/compressible_test.go create mode 100644 vendor/github.com/klauspost/compress/fse/README.md create mode 100644 vendor/github.com/klauspost/compress/fse/bitreader.go create mode 100644 vendor/github.com/klauspost/compress/fse/bitwriter.go create mode 100644 vendor/github.com/klauspost/compress/fse/bytereader.go create mode 100644 vendor/github.com/klauspost/compress/fse/compress.go create mode 100644 vendor/github.com/klauspost/compress/fse/decompress.go create mode 100644 vendor/github.com/klauspost/compress/fse/fse.go create mode 100644 vendor/github.com/klauspost/compress/fse/fse_test.go create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/00f14dd34076a71e9e54b9b88497c2a214c91d81-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/01a027e4ad99a383228779f2aaf1a2f4a3f3857b-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/028b20cc463cb40889c44f46b67d13db0c6b50a2-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/02a4a6eccf33f032b9acc928be2f5377b31d0b03-11 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0b0a852a4680d8f3fe07ad0e9997b18186918c78-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c851d4e4c8b5055b6ce3b68089892203057b3c0-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0d0de3f34f3d27f32d12be358cb2dde550d72172 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/110c8a30c16070bf2813480d9492a1a170a7d80a-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/138deac60e8494cd0329602411774ea9ba629f72-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/19aa2a437fa2a48199cc0294469a0a942ae1483a-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1b6cc66a7d78b5b1f37a7d4d7efaaeed1a6ce630-9 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1bf17f213e2aee50a14d920aa1c615edab1b4d11 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1cfd49b23106a3de30052a18cee3bed23d08f552-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1ecd000fbf02c3bd4cf7cfa7a314580789536ab0-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f2a2c8867dce3ed56fef849e5de664c20cdae39-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f969240d093a413365023cc05432790a500046a-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2547cc736e951fa4919853c43ae890861a3b3264-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/254bff7e4526a1c06684242ce8c6f32b07466192-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/26157894111c075cd978a0a67a1bd2c6184e92d6-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/283e76a3a5ac43d02ad685c555a6eb9a8fbe88e5-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/284e42ad2dbdfcfb6c7e6c7d5ad1bcc7e911f96f-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2891dddca25448c8f1671b9779f715b45e6ebef0-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2b8284f1553bb6e799466377047fff8a30e1dba0-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2c3a94ad7435a7c8ae24df733e7c3a1044b38580-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33d53df606943afe544548920b1b8bd3e1ecf731-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3473974824e5391343390e25b1e250edf2ab45cf-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/393fe96068641f74607dd7eebde0807de355944a-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ac84d808844f1204e0704eb2d87a083d17e5edf-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ca5ae6d9b3a1d465c8214e272c32a60ebc0c848-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3fc41ed16660ff04dc86763d24f7f41e7ac72e57-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/44a33b09be4119510e06b8cf5f695658dd0da430-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/463d78c147df54fb78e55f52f79c9dff7a42c5c3-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a076c6a1ff5c3956d52a9a18c90636d9271d5dc-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4c2d1f5dfeb5273fe3c44edc2c9b016159d23b5c-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4f784804ea2ba40c6ff5251b1c092c382b8ff236-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/500ce5edbda324f9a385f06a24094cee873bcf07-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/537d5d54bfa6fbdce3e0d7b7746097ba124ee7d8-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/55a0c930a804665fd0ae2aa914e39ec2898babaf-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/56032dcc54f0d2fa736dd71962caa4e3e240abf0 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/576280c2b993d7a52ac7c741273336f8bd9213f5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/59d26deac1ea4b1ad0e2d65b20839f7d2d4a4b89 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/5b4999d4bd9c1b77f6004595bc2e80bf6c7180af-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/5bf1f7b62d3967f98c64b19a4b2c0d61b70e6222-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6548f73fac595761f3cf335b35d1ff524d67f09f-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/68d516dd85ef75af6a2cd31394eebab11b024fe4-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/69c449d595dc232b2ad88b0b48395948a23a0650-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6afbd7493a57d48d401da68efdc79156ccc1992c-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b50366cad8565e61d162e38cf031c918d305dd3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b99950532c007f8f24725686d8142ddf390889b create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6d9dd11e564c301aa0a6043ee59e00c9b0192334-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6e53664c27b28370ee8680e4e4dfd139b43c2850-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6ee6aab4898dc237d1504802293ff1e36e07d7d7-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6eea60261259d0ed848b459866a9a7ccebf25f02-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/70dcd94d449aa197672f8cabcc88a21254131687 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/72677d19506938afc885d16fd5ca7c4be75f3752 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/732e566ac977d41409549e42c4b6ff6b0913b3cc-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/747d7c993787ae22ace6ec322dc1f098c938ec1f create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/764ca341b24c6a68ad9507a31abcc33287f6c994-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/7b56b7ac07966b8060919498d93a47e68730d20a-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/7d2570a230d731b54e04320f4bce5693d5bd4176 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/84859b8196cb65505cda9c056cbecb4096fd4879-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/889fdb56e3b7b79e51e66ed1c47fb0b60970d054-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/8c562007589132e496325ea892733466e03a06cb create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/8e78a58162034efce763c158087c6f1e427c1260 rename vendor/github.com/{xeipuuv/gojsonschema/json_schema_test_suite/format/data_13.json => klauspost/compress/fse/fuzz/compress/corpus/9150349979ceed8b2f6db6e0ed836462cd27d499-1} (81%) create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/91a9bc8bbcab0dc05bedaf5f4aa8d383c1651fb2-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9278d66afee65127b44cdd505e55580e1faa2377-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9355e3410f2f344ecd5dd798819020a35461c2df-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9544d0384139d241f81c841cb63f4a6bf2c3d55e-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9802e09660b74c259960141c89402b5fdececf3f create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/98840eab4f9516cedcdcc88302b3639672a42f06-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a71d9b48c814eb1b0db3133482c06a079de2bc8-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a86f34bfd765bab80845da7128ab574d6abdef1-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9cd2374f626d4c55ce9389368b428a74be518319 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9d52d6b15a5ee8cd7a575bac4dec1025573ad062-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9e6953ce446955eed1bee2d9819461068d2d37f6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a0704a231fa435579a323a222d91a03fe3b5cbc2-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a1f084b3911d33e6b41f2ba29efbf9140800444e-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a3953bd6a594600ab51268955ecee6fea8be4709-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a8e6fe772a578fe63546761ea1c195ff61203810-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/aed10bc423e56534538d83702d4be2aa281549a9-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b22334c4d7507820a3b901dcba18b20a74b28f22-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b60c99af5868c013f98cdce9781b4fffeed81f30 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b7b180de011becb75b415d308134a35b1c3e075f-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/bdd90d98c50056c82fa01cdee2d91ef30112c4d7-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c372591e0c943653714cdc9b1e52f6b0a49a0ab6-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c775292f392c027f7d24e5a1c84b1dd176c03f32 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ca269332cbd02cb17415e5cfc4ef7403875ef755-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/cedd771f15bd51b21b91d2535588e6bfd943456e create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d22b7d7f10d50e7cd68cfb65ac60ce2af5e05f0a-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d24d432b5104847324add3b047f71cfbb2cf11a2-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d2a3b921d428c6ef1dc976623d0fd3914b8b5924-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d5c5747ded386a1de2be97f8fa56f27dbf866331-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d68e96f1fdefcc1ca114970b7d9ef1cbd5a0cc50-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d9af7dc7888daf056627088aef8cfadd5817660c-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de7d905f4388e2955b0a11f42517882f0ff5792b-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e3b22b4eb898b68dde1c73dab4629c38025031db-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e55f990e122023ab58626ef27e06422b7c4be053 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e77d34eb148eb0a3b30feffc7e9b56cd182dc74c create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f52fb64e8823fdebdb11ae1c231358fcce57e638-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f748f012d8d9bd2b168aa96c529658761dd648a4-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f8f96538c274d717ccca38324c9aa658e67180dd-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fb51f26fe62e769ba34f569454121f46f2a4d277-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fca6bc86ec8711a1e7745c03237087d55d936a67 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fd155cfb10f96df4544263f5d2164351ae97f806-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fe5567e8d769550852182cdf69d74bb16dff8e29-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/057294475853d7ff15d86d889f592eb7ba6b2e72-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0d67d398462565f4d9e21f5efe9b0a6816e8962c-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/19aa2a437fa2a48199cc0294469a0a942ae1483a-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/1bf17f213e2aee50a14d920aa1c615edab1b4d11 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26157894111c075cd978a0a67a1bd2c6184e92d6-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/31a1eb16673086976295a4042ccef7fa443503df-11 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/327ed0588eb0b927e81d9b9adfd8aa98a1a5081d-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/500ce5edbda324f9a385f06a24094cee873bcf07-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/545816fc75823315f58483bdc08de39b4b26f487-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/555d303800fd439e509e0720e6d7cf04f744ec2f-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/55a0c930a804665fd0ae2aa914e39ec2898babaf-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/56032dcc54f0d2fa736dd71962caa4e3e240abf0 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/566fbce2e12fd9efdb9165b796da786e66bf036c-9 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/576280c2b993d7a52ac7c741273336f8bd9213f5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/577c882a297cbdf4233695231e12accbcc2abdcd-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/59d26deac1ea4b1ad0e2d65b20839f7d2d4a4b89 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5bf1f7b62d3967f98c64b19a4b2c0d61b70e6222-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5c795ad342ff2a0f69ada3f3382ba05013387264-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/64426d08b2cefc746ec73d04daae35a27dd53ccf create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6548f73fac595761f3cf335b35d1ff524d67f09f-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/68d516dd85ef75af6a2cd31394eebab11b024fe4-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/69c449d595dc232b2ad88b0b48395948a23a0650-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6b50366cad8565e61d162e38cf031c918d305dd3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6b99950532c007f8f24725686d8142ddf390889b create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ce2e7227237a64b8bc0b5c27f018bfd2a2227f2-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6e53664c27b28370ee8680e4e4dfd139b43c2850-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6eb5eee33ab96304ffc66043a961108878b0565f-9 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/72677d19506938afc885d16fd5ca7c4be75f3752 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/747d7c993787ae22ace6ec322dc1f098c938ec1f create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/764ca341b24c6a68ad9507a31abcc33287f6c994-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7b56b7ac07966b8060919498d93a47e68730d20a-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8c562007589132e496325ea892733466e03a06cb create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8e78a58162034efce763c158087c6f1e427c1260 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9278d66afee65127b44cdd505e55580e1faa2377-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9802e09660b74c259960141c89402b5fdececf3f create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/98840eab4f9516cedcdcc88302b3639672a42f06-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9a3d36ff249d8734de00dcaec41bcbf160adaecf-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9cd2374f626d4c55ce9389368b428a74be518319 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9e6953ce446955eed1bee2d9819461068d2d37f6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/a3953bd6a594600ab51268955ecee6fea8be4709-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ae1137dce39774d2ba19b77b1fc915c57ba95523-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b60c99af5868c013f98cdce9781b4fffeed81f30 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/bedb6456c65af2ca319c6630db22f2e362dd73f2-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c2d596d0601332a809c19c0347580c78b079f822-8 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c775292f392c027f7d24e5a1c84b1dd176c03f32 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/cedd771f15bd51b21b91d2535588e6bfd943456e create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-9 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da3ec0c217bfb46b23a5044192571ae8eb5bd2b7-9 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de0ea11f2f9d6c773542b53337f688d655918f76-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de15b9702bd007145d26f7b5ddea83a93ecee381-5 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e395861f9b34c58744c48a34a0d471241957cec5-2 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e55f990e122023ab58626ef27e06422b7c4be053 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e77d34eb148eb0a3b30feffc7e9b56cd182dc74c create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ec8f2472897dd80c1c5f5c958c665d18a8602e55-10 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/f748f012d8d9bd2b168aa96c529658761dd648a4-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/f8f96538c274d717ccca38324c9aa658e67180dd-1 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fca6bc86ec8711a1e7745c03237087d55d936a67 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fd155cfb10f96df4544263f5d2164351ae97f806-4 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fdd2a48761f050f1f83fa279882eee5c8378f9d9-3 create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/run-compress.cmd create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz/run-decompress.cmd create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz_compress.go create mode 100644 vendor/github.com/klauspost/compress/fse/fuzz_decompress.go create mode 100644 vendor/github.com/klauspost/compress/fse/highbit_go19.go create mode 100644 vendor/github.com/klauspost/compress/fse/highbit_old.go create mode 100644 vendor/github.com/klauspost/compress/huff0/.gitignore create mode 100644 vendor/github.com/klauspost/compress/huff0/bitreader.go create mode 100644 vendor/github.com/klauspost/compress/huff0/bitwriter.go create mode 100644 vendor/github.com/klauspost/compress/huff0/bytereader.go create mode 100644 vendor/github.com/klauspost/compress/huff0/compress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/compress_test.go create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress_test.go create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/01ace8efdfd46d82b0fef511b259933ced9d13ec-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/049f4a878ab48c404bd0950e2366e3c0eaad4318-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0dde84d337ceb9269489c3919d205ea9789c158a-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0e90b9893889f69194ca72e28082a1f6081c4b35-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/112b9d35e8cbeabce6fda543aec804ab83185543-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/130efc33e0d8f0327a73110deac85474bc91dc8d-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/234ec5ad1fc105fcc08523ff91bd8430284aa1f3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/26ccc59f9c4d89063210f2e8ddd0c26394c2a607-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/287d18afe5e0d54d4554a39aa2acff99d696136d create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/29e95908e0f3e9f3e189441de6ed797b7bee2449-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2c93d4381a547aa7001acfffcf51dc323a0cdf2b-10 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e0d10ca05bdebe3fe84c481004adb11a1cc761c-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e85ccbaa127cbf77bb8f0b5c3afdcf53f63f2d8-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/30632e96a06600a75b47b4cbe0db74b959d09aa5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/308f53f64ce26d56e4379931ff3611a7dd49325f-10 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/31e020e2f79260ddcbf377c8e1256288b57d32b8-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/32a3cf4aef238d77278831c3744c1327dcc8f8c0-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/350b061ff78cfb97b28716ec96e27f616d439f97-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3542214eb977ea9bdabcc55601d7876b6227b501-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3693a58b98ececb7670844f49caa795c1735ddf0-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3b1d88a86a30b301e5f509a756f43ef34fad55b0-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/40b8de701a171fddefdc4459023121a1e605b16c create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43a26357597ae65521480220432ff645450d01f1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4869e00fbc61867ccab5b83187c3a146ecb36775 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/489d689da4860f3116a62db6b089bb0d5ba4de40 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/48bc76aeb21bc6070323247927d87e591e51eaa9-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4959a4a9db83af17f9368cf490b8a0356d872147-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/49dce428e704656d5a4f1053a443ba44f51e91f0-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4a98d52bab6ca703e4521093afa2a400e10f4a7d-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4b4859f278820e969c13c975669322e2c9df9823-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4d1adbc376464b88c52a00ed562cdacbffa4af1a-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4f506d462241876610a0f92a5aa1e2b38ea8722c-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/51bdcd2cbd098b042fddc528083572bdbcfbe449-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/51c91bfe65eaa40fe4144306d6332ad84e4bb8ed-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/53bcc0e78275d3efe9e012e6d30412066bf354f9-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/545828581071b0d01c3fd9d15c7850c3f83ea15f-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/56860900c11ef30e85ce99b14e0e687745b269ae-9 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/581ed2fb7f25a6a5a8de40beae3dfd1666c511d0-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5b5d4262260375deb5146e3fa43f689923e856a7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5c4b6679ee378f2533b099450ed21e40d54f6cd0-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e13404b6713db5f2d4972747da143057beaaf64-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e6c62abd0fe49668d26e9bfced0ef0dc699f6a5-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e701f4039d099c3a15c4e8d9b070eafc96de0e9 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5f9642a02959a51bf5a67e5347d702fe0ba6af79 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5fcc48ee5b52b608e5d909ca4eddae9bd8f3a6ae-8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/60031506809cb3ff39b549968772a652cdaf8e1d-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/60df0cda93981b671836008ff12625cd51171e9d create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/61077e99c801f3eb732ba4fae2296091eaea9c01-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/612edfc64ec2f157158ac6b0b7bdceeb1338d3b8-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/617132f8209014d1839691bc6c7d77e70ed60095-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6182f2935dfb8967ce0d259c3fbc143167528f3b-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64bd2417583750313dd74d25c8b2f3eed25909a8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64dae3270e5806311fac4518cef7b473e2d3cd91-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/67519fd21225a9a0f3c5a86a76de43fd7234e1d4-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6b8432daf9022411b253dd7c8f5611c22cdc3895-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6d44323de19d56374597e2ac06e3beee133a42df create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/72fa415daeee2a5f74a86a035e9dda32a29e34e4-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/747e5c3eed27e2c0a7a8987c78981b9cece0150c-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/780851224f52ce3b64a90ba56b4fc567aba4cd3d-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7d233588c41ecc575034228477393f70d8acb5fd-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7f255b276b164c4309adbab19b872422d979c5e5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7fca1fadd76fce238c82e9542eb05acd5bd38653-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8036c610dcec87d7bc42ba4ddddd660372392268-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/82186327d4a14ac0da15581a5c7f37e83df72cf5-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/85bb13fef173edaeb7be4e6675bf8374bf136d9c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/85d8aceca37403b2a0b6ed82502afd40f2513541 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/872784ffeda8c586972151364e6917bc0fb463d2-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/88b9cf63d84dab51dd67f44df0e64977da9dd7f2-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/88c2814de9919316170e12c1cbe39ff2a4e3dc69-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/89f86a63a2de2d2877451bceaa2bd4e38abc8e64-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8c6d7def5f4465fc685347875a8e64e108b393df create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d43559e0f27f4a754db78baa697b37013f8a01d-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d69ef1f7f28824fd8267ae8b36833e3e0b94765 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9239364aad81b3afb16be9487b5721a6fce7d375-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9508e90548b0440a4a61e5743b76c1e309b23b7f-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9567d94166370de252e759169b215fa8c2288746-11 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/962ecf57ef5bbb4107aaff02072f03d3316077c9-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/96629c94c3faec6af9790f99bd72567d4534f9db create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9aa393616dd8a00cd97be9a58bf70a9b4164d802-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9b3ec560e1ed89789a09e834a18fb9f1d042f5dd-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9c61b17678d14d0b9ae09be017c6bbd6a3c3cabe-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9e3fc7fad4bf135219a974a8dac87e366f5b8e8c-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a0bd71e19da9f0265508cdd2a50a458e5cd6bb19 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a3c5cb453e89aef7359f952459685c26cea30d63-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a48f8d3562980d5cd8b9f0eb3859ee562d7c0596 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a5ef3d034850ec9510bb931f21a1547518a76f14 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a70573a8edabc05a2431773757158ac90e63d43a-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d099f456e0a9444c10bf1cdfe788da8f65f8d5-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d2bd34ee5b24064975a68298bfa566b63a133c-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ac04c28afed2d337f787d007a992e8ec7f937b36 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ad336c19a004476640934db99f827f2917a09bf8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/aef8193ef7e7916cebd428e02ae7c9081b9e56a1-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/af640328532d29ae2f935b87564cb595f6cbb54e create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/b16d3306a414bbbffd9344eb00f460a160fb06bc create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/b585a3f5c60ffeef5d5bf13dccca17199d7ab311-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/b776d26f33e5cb69dd1ee1bd66da9024509c62b6-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ba4b4565a95f651dd9c3e90b0742db3a422498e1-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bcd851430da545599a636bdf22499157116d652a create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bd0ec04037fbff5629b94a88915ce29cfa3c9f9e create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf297fbc5cd66aeca02688585a23f98a9f0081f5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf30493a58dc0fad8c77816086b2b32875cade69-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c05bf2b6c368beec9fe1ab4172da851e547b1e49-9 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c07ac5a6c29ec72f00d7fe9cfcd9900ebf6fcc1a create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c4d93c018e1686a8e4aaf0a4dad8d60fecd13675-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c64b47ad9a354cefde19e93efca0d656a20fe024-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c6f1d808e0fd8c0a973e1b251e93ddae5930638e-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c7fd10d5817ad18dcb798e82328e8a7b087fbbea-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/cb7cd34cfe31060ee210487d4d2eb6c1811e67c5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/cc6c7d741d3c9c4c6ceb1461068d6ec970805e3d create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/cdd398e0ae2a152bcb53d296a63e1e8ccaabb75b-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d2142c494b1f6526189f383e88037cd4c05e16bb create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d237dcb7a55a9542fbe886c9631804dea200b56a-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d38389226ead13791d80008cc5fb1eef75aa0be4-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d977ecea3fcbb78028aabdb98bf098594d5eaba7-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dba30063a9e305d125c83f435e35e0aaa33c560c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dc2f0ff7f3e2d2a2b290bf36e85c695506c68782 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ddaf0bfb51c7134e58a010fe0a099e76e7bca7f6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ddc3609a7e8f2da5428973c80847b1ae0bc74af7-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dde60ed75565b253fc44c8543a788dbef7b9a53f-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1170c6fe09522cb50935557856ba9d85c2b37de-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1323173b156c91190a3b84ca33c955550404ade-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e295ba780df856ae31513226b96e8382063d034d create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e36bba8cd1c971edf6696aa76dfaf690e21e08c3-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e4862372d6534ac4eb19df7d21840887b8297df8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e6722bb760655d9d3dbbdc4f9ebf7354a2461d97 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e77ce13737af5a84c7a50d9d18a6699fb862c63b-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e85ca8b54d82486ba7462ea0659c42a0a36cdb71-8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ea616ea4310406f7893091a96e87e0b9c0412e4b-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ed0f1c5ee2700c3c2d9a0914de90363e750c3f47-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ee481cbb8636f3957618b3e627cc6a56caa1dce5-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/efa3bc9831786d0e203957fd2ac2c4de9d5c168a-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0121676050a7bb84ade5c4783407e0527ca88a4-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0bd04a4f5ccd427cf59b79e2f67caafdbfa0233-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f2a68d20b1e145bbf69037f17685e0adedfe68a4-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f320b3ab9e260a1bbd378762c54a8e23f794901a-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f5829f8a97a0a1dc008752245b460db0a0459c03 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f62e0a3c0c8bd15aa0b2f991898f2d27d2964d44-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f670ffe6dc8a8e0b45bfa675672498f90b44001e-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f7a76f4c851f342d0d576ffa71329438e109347c create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f8d134ecc8e30461236ed7b28aeb29bc2987e50e-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ffc64298b00af19e0f953728f42fa8e915d7b470 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/00018ebe176ab4fa757c5da39cd8b2270f12de24-10 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0170787897b2aec4a4477ab507777ad13eb00e10-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0297e0b01e8ace9ec3a22311966681bbe06b875f-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04fe6043558c921672856d1d9332bb41b7d64087-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/05575bdaa6ba33f22d304f9f3a62010e42f76acf-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0ceda9053c751bf974334c7c1676832feea92d69-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0e90b9893889f69194ca72e28082a1f6081c4b35-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1050baf5be0eeaa50c7e2ccd22c386146d582668-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/112b9d35e8cbeabce6fda543aec804ab83185543-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/112b9d35e8cbeabce6fda543aec804ab83185543-1-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/118873131212b4f8e4f2b7aa9e398911bf83fb21-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/12a386209a550aec21fbfa0b2ec8c066fe131db7-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/17a53cfc55c261af6e258f0effbe34a9d0c3a117-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/182516c486b2eafc720a03046af1949a758ff7b4-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1e23aabdf832d3bd167105c98f4931313e0df945-8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/223bb6b768c691e0f2eb62db5821b8678a9ecc93-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/2273a03f5b8fe56f4bbb7f7e9560c440fb8237c8-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/234ec5ad1fc105fcc08523ff91bd8430284aa1f3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/234ec5ad1fc105fcc08523ff91bd8430284aa1f3-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/236bd270f4d36e14eaf41daf5bf33e55ff5f463d-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/269f2e5e3b3b1acba92aefd0a49444d0869af5ae-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/2805bdad6bc68c3c6edd9344d658b6d43a8dbcbc-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3187c5cc2c8b927997cbd46e9328581620116613-12 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/34e0f846cc18c5c0a6e0334192411dc2c6a1c719-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/36971f66110d363f2a217d16bf1913475c25a862-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/38729163260fdf7a5526f17de3cb34f02661e8c9-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3885c38b78f31c98dd73bc1fa7d6dfe467eb0fa4-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3aa823c93e1ed004c38d32fc9f96c9f6036e7c77-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3c48a486a1b94dc9df2201c25f411123cedd119c-10 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3cee784d376938121b711cd56f71a68f3496cda8-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40fbf19f5ba46c802a2755c71c852b92fc334dd4-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43a26357597ae65521480220432ff645450d01f1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43a26357597ae65521480220432ff645450d01f1-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/44678db801ad65c4ba51cc5e0cd9095852f329cd-9 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/475dfd55b54d9a0a4287ab8b952f606f2773a49c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4869e00fbc61867ccab5b83187c3a146ecb36775 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4869e00fbc61867ccab5b83187c3a146ecb36775-4x create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/489bdb7862474650462b753ed85d2a123d1730ca-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4bb7d1adac51afa9ac4650ee8ae5203297aa8fec-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/542e60846887c634378dd1b29d3ce29b90e13f99-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/54fbf0fc6ed4319b2c0986f26c3a142b194d9ca3-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5889a9b84fb69d2913d474a381ddceb217137d06-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5b85e7d11f14ff2864b2c56e03188f15e52fd9bb-8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/649971daa4b93c4ffe6190415f22569030f2300a-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6903fccf79c27b4cffe21090d03c6879cbb72274-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/695a09b31703a8f7f00422a62549912c31263506-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6a88ce804bf81bb01a233527595b27668cca331d-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6c16b84194ac60c492487044ed3ee744c506faf6-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6cdd7b3f70c2448bb4f666c8bc5aa6a890a34f7a-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/73e369adcad522a27653be74fe4a9ff8d30ea19e-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/7f1623aee483c22124f8ecd37ad62c5acc932304-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/87e26a4d86b6f1ffba523d73bdf7479715faa6c0-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/8af40c705337fe65b50643a231029a953ea998af-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/913987cb3ea3aa8df9fabade3b6440bfb0e14019-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/94b18a8ac5c2cd3b040754e236dadeae895b3dae-13 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9835e8bdcd54890f9ff4dfdb634b5a6dc254f09e-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9f3d543656b54b38ac84f009a626bdfb074393cb-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/a70fe33ef1a23361593e5d25ed782c2b4ee22813-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ab076dfc3f75d3a603806cbf3ab318bab8575591-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ac8feec2af44db5a6eafff09781dc9c922fc1380-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/aeb91ce9a4b3547b57a3ab02add1500b6d6447a8-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/af04c0ac0c9608e913ab0f27a1426630adc72f57-8 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/b8fceb6a5aa974b33d2dc94526c96a3d46633e89-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ba01d6cf0fb9c71370ef35d6c6cebb1fa75018f6-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/bf49b2edbbb9da8b0c135b3ed5e5a5a7e77e61a9-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c03c780b2d547bf3157d929730d554533b570acc-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c37533eda04d4cd770cce546fd0db044407d765c-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c3793d6b45cba4a91dc18770c1c2a9946d334258-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c9d84a90c00d2393354dd80dbb9d26e8edd387e0-10 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d06c109bc27d8914b330b99ac8262cbceda79b4f-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d1f80ef35b58a2366e5b133473dc273f3740d57b-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d2e694ef05e527e478769df82b0f65fb3b442a45-1 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/db3bda50ea81814214d6e6c511736731a44d7b9a-2 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ddf623fc42f256fbee77d98e0c341d8f8e967d6f-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/e7416101c16988f1aa4ad09e2e0ea26698a69fd5-6 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/eae606b8c2871f94da1b8190d095e686e9f2eebc-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ec2c23b0ecfb55422bb7376b9de762f0cb2daabc-5 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ee5e3543ec53aa392b7485e16163661dc45c61b8-3 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/f317ba679fa2f7020fd501a5ceb78a12da06a817-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fa0258e24eecdba8b3e9355740c458120b4babce-7 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fab8c92bc4068e05f10d9b1978a34bfd5a0c12da-4 create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/run-compress.cmd create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz/run-decompress.cmd create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz_compress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/fuzz_decompress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/highbit_go19.go create mode 100644 vendor/github.com/klauspost/compress/huff0/highbit_old.go create mode 100644 vendor/github.com/klauspost/compress/huff0/huff0.go create mode 100644 vendor/github.com/klauspost/compress/testdata/case1.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/case2.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/case3.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/crash1.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/crash2.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/crash3.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/crash4.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/crash5.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/dec-hang1.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/dec-hang2.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/dec-hang3.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/dec-symlen1.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/endnonzero.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/endzerobits.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/normcount2.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/pngdata.bin create mode 100644 vendor/github.com/klauspost/compress/testdata/sharnd.out delete mode 100644 vendor/github.com/klauspost/crc32/.gitignore delete mode 100644 vendor/github.com/klauspost/crc32/.travis.yml delete mode 100644 vendor/github.com/klauspost/crc32/README.md delete mode 100644 vendor/github.com/klauspost/crc32/crc32.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64.s delete mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64p32.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64p32.s delete mode 100644 vendor/github.com/klauspost/crc32/crc32_generic.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_otherarch.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_s390x.go delete mode 100644 vendor/github.com/klauspost/crc32/crc32_s390x.s delete mode 100644 vendor/github.com/klauspost/crc32/crc32_test.go delete mode 100644 vendor/github.com/klauspost/crc32/example_test.go create mode 100644 vendor/github.com/lib/pq/TESTS.md create mode 100644 vendor/github.com/lib/pq/connector.go create mode 100644 vendor/github.com/lib/pq/connector_example_test.go create mode 100644 vendor/github.com/lib/pq/connector_test.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go rename vendor/github.com/mattn/go-sqlite3/{sqlite3_omit_load_extension.go => sqlite3_load_extension_omit.go} (99%) create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go rename vendor/github.com/mattn/go-sqlite3/{sqlite3_fts3_test.go => sqlite3_opt_fts3_test.go} (100%) rename vendor/github.com/mattn/go-sqlite3/{sqlite3_fts5.go => sqlite3_opt_fts5.go} (90%) rename vendor/github.com/mattn/go-sqlite3/{sqlite3_icu.go => sqlite3_opt_icu.go} (63%) create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go rename vendor/github.com/mattn/go-sqlite3/{sqlite3_json1.go => sqlite3_opt_json1.go} (85%) create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go rename vendor/github.com/mattn/go-sqlite3/{sqlite3_vtable.go => sqlite3_opt_vtable.go} (98%) rename vendor/github.com/mattn/go-sqlite3/{sqlite3_vtable_test.go => sqlite3_opt_vtable_test.go} (99%) create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go create mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go create mode 100644 vendor/github.com/mattn/go-sqlite3/static_mock.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/tool/upgrade.go create mode 100644 vendor/github.com/mattn/go-sqlite3/upgrade/package.go create mode 100644 vendor/github.com/mattn/go-sqlite3/upgrade/upgrade.go create mode 100644 vendor/github.com/miekg/dns/length_test.go create mode 100644 vendor/github.com/rs/cors/examples/buffalo/server.go create mode 100644 vendor/github.com/rs/cors/examples/gin/server.go create mode 100644 vendor/github.com/rs/cors/go.mod create mode 100644 vendor/github.com/rs/cors/wrapper/gin/gin.go create mode 100644 vendor/github.com/rs/cors/wrapper/gin/gin_test.go delete mode 100644 vendor/github.com/satori/go.uuid/.travis.yml delete mode 100644 vendor/github.com/satori/go.uuid/LICENSE delete mode 100644 vendor/github.com/satori/go.uuid/README.md delete mode 100644 vendor/github.com/satori/go.uuid/codec.go delete mode 100644 vendor/github.com/satori/go.uuid/codec_test.go delete mode 100644 vendor/github.com/satori/go.uuid/generator.go delete mode 100644 vendor/github.com/satori/go.uuid/generator_test.go delete mode 100644 vendor/github.com/satori/go.uuid/sql.go delete mode 100644 vendor/github.com/satori/go.uuid/sql_test.go delete mode 100644 vendor/github.com/satori/go.uuid/uuid.go delete mode 100644 vendor/github.com/satori/go.uuid/uuid_test.go delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_30.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_31.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_40.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_4.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_13.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_13.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_15.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_22.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_23.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_24.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_05.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_06.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_07.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_08.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_09.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_15.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_16.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_17.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_18.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_19.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_22.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_23.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_24.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_25.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_26.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_27.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_28.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_29.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_30.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_4.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_5.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_6.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_7.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_22.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_13.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_15.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_22.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_23.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_24.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_25.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_26.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_4.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_13.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_15.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_16.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_17.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_30.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_31.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_32.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_40.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_41.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_50.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_51.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_4.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_5.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_30.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_31.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_05.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_06.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_10.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_11.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_12.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_13.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_14.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_15.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_16.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_20.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_21.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_22.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_23.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_24.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_25.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_26.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_30.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_31.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_32.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_33.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_34.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_35.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_36.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_40.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_41.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_42.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_43.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_44.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_45.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_46.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_50.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_51.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_52.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_53.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_54.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_55.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_56.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_60.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_61.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_62.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_63.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_64.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_65.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_66.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_70.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_71.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_72.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_73.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_74.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_75.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_76.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_0.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_1.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_2.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_3.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_4.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_5.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_6.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_7.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_00.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_01.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_010.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_011.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_012.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_02.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_03.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_04.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_05.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_06.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_07.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_08.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_09.json delete mode 100644 vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/schema_0.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/jsonschema_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/allOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/anyOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/default.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/definitions.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/dependencies.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/enum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/items.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maximum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minimum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/multipleOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/not.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/oneOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/bignum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/ecmascript-regex.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/format.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/zeroTerminatedFloats.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/pattern.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/patternProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/properties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/ref.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/refRemote.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/required.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/type.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/uniqueItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/allOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/anyOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/boolean_schema.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/const.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/contains.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/default.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/definitions.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/dependencies.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/enum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMaximum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMinimum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/items.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maximum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minimum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/multipleOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/not.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/oneOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/bignum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/ecmascript-regex.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/format.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/zeroTerminatedFloats.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/pattern.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/patternProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/properties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/propertyNames.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/ref.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/refRemote.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/required.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/type.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/uniqueItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/allOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/anyOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/boolean_schema.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/const.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/contains.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/default.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/definitions.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/dependencies.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/enum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMaximum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMinimum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/if-then-else.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/items.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maximum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minItems.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minLength.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minimum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/multipleOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/not.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/oneOf.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/bignum.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/content.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/ecmascript-regex.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date-time.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/email.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/hostname.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-email.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-hostname.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv4.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv6.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri-reference.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/json-pointer.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/regex.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/relative-json-pointer.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/time.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-reference.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-template.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/zeroTerminatedFloats.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/pattern.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/patternProperties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/properties.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/propertyNames.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/ref.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/refRemote.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/required.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/type.json create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/uniqueItems.json rename vendor/github.com/xeipuuv/gojsonschema/{json_schema_test_suite/ref/schema_6.json => testdata/extra/fragment_schema.json} (100%) rename vendor/github.com/xeipuuv/gojsonschema/{json_schema_test_suite/refRemote/remoteFiles => testdata/remotes}/folder/folderInteger.json (100%) rename vendor/github.com/xeipuuv/gojsonschema/{json_schema_test_suite/refRemote/remoteFiles => testdata/remotes}/integer.json (100%) create mode 100644 vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/name.json rename vendor/github.com/xeipuuv/gojsonschema/{json_schema_test_suite/refRemote/remoteFiles => testdata/remotes}/subSchemas.json (100%) create mode 100644 vendor/github.com/yalp/jsonpath/.travis.yml create mode 100644 vendor/github.com/yalp/jsonpath/LICENSE create mode 100644 vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go create mode 100644 vendor/golang.org/x/crypto/acme/http.go create mode 100644 vendor/golang.org/x/crypto/acme/http_test.go create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go create mode 100644 vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go create mode 100644 vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go create mode 100644 vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s create mode 100644 vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go create mode 100644 vendor/golang.org/x/crypto/internal/chacha20/xor.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go create mode 100644 vendor/golang.org/x/crypto/nacl/sign/sign.go create mode 100644 vendor/golang.org/x/crypto/nacl/sign/sign_test.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_noasm.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.s create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s create mode 100644 vendor/golang.org/x/crypto/poly1305/vectors_test.go create mode 100644 vendor/golang.org/x/crypto/sha3/hashes_generic.go create mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.go create mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.s create mode 100644 vendor/golang.org/x/crypto/sha3/shake_generic.go create mode 100644 vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c create mode 100644 vendor/golang.org/x/net/html/testdata/go/template.dat create mode 100644 vendor/golang.org/x/net/html/testdata/webkit/ruby.dat create mode 100644 vendor/golang.org/x/net/html/testdata/webkit/template.dat create mode 100644 vendor/golang.org/x/net/http/httpguts/guts.go rename vendor/golang.org/x/net/{lex/httplex => http/httpguts}/httplex.go (97%) rename vendor/golang.org/x/net/{lex/httplex => http/httpguts}/httplex_test.go (99%) create mode 100644 vendor/golang.org/x/net/http2/go111.go create mode 100644 vendor/golang.org/x/net/http2/h2c/h2c.go create mode 100644 vendor/golang.org/x/net/http2/h2c/h2c_test.go create mode 100644 vendor/golang.org/x/net/http2/h2demo/Dockerfile create mode 100644 vendor/golang.org/x/net/http2/h2demo/Dockerfile.0 create mode 100644 vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml create mode 100644 vendor/golang.org/x/net/http2/h2demo/service.yaml create mode 100644 vendor/golang.org/x/net/http2/not_go111.go create mode 100644 vendor/golang.org/x/net/icmp/diag_test.go delete mode 100644 vendor/golang.org/x/net/icmp/ping_test.go create mode 100644 vendor/golang.org/x/net/internal/socks/client.go create mode 100644 vendor/golang.org/x/net/internal/socks/dial_test.go create mode 100644 vendor/golang.org/x/net/internal/socks/socks.go create mode 100644 vendor/golang.org/x/net/internal/sockstest/server.go create mode 100644 vendor/golang.org/x/net/internal/sockstest/server_test.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo.c create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mipsx.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_ppc64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_test.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.s create mode 100644 vendor/golang.org/x/sys/plan9/asm_plan9_arm.s create mode 100644 vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go create mode 100644 vendor/golang.org/x/sys/unix/aliases.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_darwin_test.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_dragonfly_test.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_netbsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_openbsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_solaris_test.go create mode 100644 vendor/golang.org/x/sys/unix/example_test.go rename vendor/golang.org/x/sys/unix/{flock.go => fcntl.go} (70%) rename vendor/golang.org/x/sys/unix/{flock_linux_32bit.go => fcntl_linux_32bit.go} (100%) create mode 100644 vendor/golang.org/x/sys/unix/ioctl.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/xattr_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/xattr_test.go create mode 100644 vendor/golang.org/x/sys/windows/aliases.go create mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/recovery.go rename vendor/golang.org/x/text/{message/pipeline/testdata/test1 => cmd/gotext/examples/extract/locales}/extracted.gotext.json (71%) mode change 100644 => 100755 delete mode 100644 vendor/golang.org/x/text/cmd/gotext/examples/extract_http/catalog_gen.go rename vendor/golang.org/x/text/cmd/gotext/examples/extract_http/locales/{en/out.gotext.json => extracted.gotext.json} (60%) mode change 100644 => 100755 delete mode 100644 vendor/golang.org/x/text/cmd/gotext/update.go delete mode 100644 vendor/golang.org/x/text/message/pipeline/go19_test.go delete mode 100644 vendor/golang.org/x/text/message/pipeline/pipeline_test.go delete mode 100644 vendor/golang.org/x/text/message/pipeline/testdata/test1/catalog_gen.go delete mode 100644 vendor/golang.org/x/text/message/pipeline/testdata/test1/catalog_gen.go.want delete mode 100644 vendor/golang.org/x/text/message/pipeline/testdata/test1/catalog_test.go delete mode 100644 vendor/golang.org/x/text/message/pipeline/testdata/test1/extracted.gotext.json.want delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/de/messages.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/de/out.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/de/out.gotext.json.want delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/en-US/messages.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/en-US/out.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/en-US/out.gotext.json.want delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/zh/messages.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/zh/out.gotext.json delete mode 100755 vendor/golang.org/x/text/message/pipeline/testdata/test1/locales/zh/out.gotext.json.want delete mode 100644 vendor/golang.org/x/text/message/pipeline/testdata/test1/test1.go diff --git a/Gopkg.lock b/Gopkg.lock index c994801..9584248 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,224 +2,358 @@ [[projects]] + digest = "1:289dd4d7abfb3ad2b5f728fbe9b1d5c1bf7d265a3eb9ef92869af1f7baba4c7a" name = "github.com/BurntSushi/toml" packages = ["."] + pruneopts = "" revision = "b26d9c308763d68093482582cea63d69be07a0f0" version = "v0.3.0" [[projects]] + digest = "1:9ceecb4271682fd824475d451b6abf02b99ad04e72f8de3408a9d8b7fd15b933" name = "github.com/ajg/form" packages = ["."] + pruneopts = "" revision = "cc2954064ec9ea8d93917f0f87456e11d7b881ad" version = "v1.5" [[projects]] + digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:358f9731027e87f8ae3a7e52f0473031be47d1e041295b3c0afc84dc779c0666" name = "github.com/erikstmartin/go-testdb" packages = ["."] + pruneopts = "" revision = "8d10e4a1bae52cd8b81ffdec3445890d6dccab3d" [[projects]] + digest = "1:55848e643a99a9dfceb19e090ce67111328fbb1780f34c62a0430994ff85fb90" name = "github.com/fatih/structs" packages = ["."] + pruneopts = "" revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" version = "v1.0" [[projects]] branch = "master" + digest = "1:7a98bc5cfa8e0c82156a33edb7ed582a9e700af089994e1b89bdb8517cd2db58" name = "github.com/gavv/httpexpect" packages = ["."] - revision = "c44a6d7bb636b17e880a53998a7f7061a56ffacb" + pruneopts = "" + revision = "bdde308713130a703436e014ff782958c251d20a" [[projects]] branch = "master" + digest = "1:44e52e928b91a686e2b9518f7eea82ba729d227d94b69574416bbe2d9d418b33" name = "github.com/gavv/monotime" packages = ["."] + pruneopts = "" revision = "6f8212e8d10df7383609d3c377ca08884d8f3ec0" [[projects]] branch = "master" + digest = "1:9abc49f39e3e23e262594bb4fb70abf74c0c99e94f99153f43b143805e850719" name = "github.com/google/go-querystring" packages = ["query"] + pruneopts = "" revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" [[projects]] + digest = "1:c1d7e883c50a26ea34019320d8ae40fad86c9e5d56e63a1ba2cb618cef43e986" + name = "github.com/google/uuid" + packages = ["."] + pruneopts = "" + revision = "064e2069ce9c359c118179501254f67d7d37ba24" + version = "0.2" + +[[projects]] + digest = "1:788735d9cba7f51b7cc86e6c7ba7b40b0b7c7b374bf3a0b5fa7c929fa2af2da8" name = "github.com/imkira/go-interpol" packages = ["."] + pruneopts = "" revision = "5accad8134979a6ac504d456a6c7f1c53da237ca" version = "v1.1.0" [[projects]] + digest = "1:3c818dada3e41bdb0f509f78e6775610f1bb179449ec8c4c86a45fae35460f3f" name = "github.com/julienschmidt/httprouter" packages = ["."] + pruneopts = "" revision = "8c199fb6259ffc1af525cc3ad52ee60ba8359669" version = "v1.1" [[projects]] + digest = "1:4d0614a5d2e5e394368521b087428b2996ae95ebc4699afabc61adac9b7cec38" name = "github.com/klauspost/compress" - packages = ["flate","gzip","zlib"] - revision = "6c8db69c4b49dd4df1fff66996cf556176d0b9bf" - version = "v1.2.1" + packages = [ + "flate", + "gzip", + "zlib", + ] + pruneopts = "" + revision = "b939724e787a27c0005cabe3f78e7ed7987ac74f" + version = "v1.4.0" [[projects]] + digest = "1:f0117357f14b0a625ddbbe25e23637291ac0276402fcfd25fc447422456364ce" name = "github.com/klauspost/cpuid" packages = ["."] + pruneopts = "" revision = "ae7887de9fa5d2db4eaa8174a7eff2c1ac00f2da" version = "v1.1" -[[projects]] - name = "github.com/klauspost/crc32" - packages = ["."] - revision = "cb6bfca970f6908083f26f39a79009d608efd5cd" - version = "v1.1" - [[projects]] branch = "master" + digest = "1:09792d732b079867772cdbabdf7dc54ef9f9d04c998a9ce6226657151fccbb94" name = "github.com/lib/pq" - packages = [".","oid"] - revision = "27ea5d92de30060e7121ddd543fe14e9a327e0cc" + packages = [ + ".", + "oid", + ] + pruneopts = "" + revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" [[projects]] + digest = "1:bc03901fc8f0965ccba8bc453eae21a9b04f95999eab664c7de6dc7290f4e8f4" name = "github.com/mattn/go-sqlite3" packages = ["."] - revision = "6c771bb9887719704b210e87e934f08be014bdb1" - version = "v1.6.0" + pruneopts = "" + revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4" + version = "v1.9.0" [[projects]] + digest = "1:4c8d8358c45ba11ab7bb15df749d4df8664ff1582daead28bae58cf8cbe49890" name = "github.com/miekg/dns" packages = ["."] - revision = "5ec25f2a5044291b6c8abf43ed8a201da241e69e" - version = "v1.0.3" + pruneopts = "" + revision = "5a2b9fab83ff0f8bfc99684bd5f43a37abe560f1" + version = "v1.0.8" [[projects]] branch = "master" + digest = "1:fe67641b990bdc1802f8a1e462a4924210a8762a8a17b72e09656049c906b871" name = "github.com/moul/http2curl" packages = ["."] + pruneopts = "" revision = "9ac6cf4d929b2fa8fd2d2e6dec5bb0feb4f4911d" [[projects]] + digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + digest = "1:78c9cf43ddeacd0e472f412082227a0fac2ae107ee60e9112156f9371f9912cf" name = "github.com/rs/cors" packages = ["."] - revision = "7af7a1e09ba336d2ea14b1ce73bf693c6837dbf6" - version = "v1.2" + pruneopts = "" + revision = "3fb1b69b103a84de38a19c3c6ec073dd6caa4d3f" + version = "v1.5.0" [[projects]] - name = "github.com/satori/go.uuid" - packages = ["."] - revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" - version = "v1.2.0" - -[[projects]] - branch = "master" + digest = "1:3962f553b77bf6c03fc07cd687a22dd3b00fe11aa14d31194f5505f5bb65cdc8" name = "github.com/sergi/go-diff" packages = ["diffmatchpatch"] + pruneopts = "" revision = "1744e2970ca51c86172c8190fadad617561ed6e7" + version = "v1.0.0" [[projects]] + digest = "1:3fcbf733a8d810a21265a7f2fe08a3353db2407da052b233f8b204b5afc03d9b" name = "github.com/sirupsen/logrus" - packages = [".","hooks/test"] - revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" - version = "v1.0.4" + packages = [ + ".", + "hooks/test", + ] + pruneopts = "" + revision = "3e01752db0189b9157070a0e1668a620f9a85da2" + version = "v1.0.6" [[projects]] + digest = "1:c587772fb8ad29ad4db67575dad25ba17a51f072ff18a22b4f0257a4d9c24f75" name = "github.com/stretchr/testify" - packages = ["assert","require"] - revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c" - version = "v1.2.0" + packages = [ + "assert", + "require", + ] + pruneopts = "" + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" [[projects]] branch = "master" + digest = "1:857a9ecd5cb13379ecc8f798f6e6b6b574c98b9355657d91e068275f1120aaf7" name = "github.com/valyala/bytebufferpool" packages = ["."] + pruneopts = "" revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7" [[projects]] branch = "master" + digest = "1:ed95b0b73de30dc5507de18b0cd6a2b79dc0ef685eefeb27fd1386f7a4e04f2b" name = "github.com/valyala/fasthttp" - packages = [".","fasthttputil","stackless"] + packages = [ + ".", + "fasthttputil", + "stackless", + ] + pruneopts = "" revision = "e5f51c11919d4f66400334047b897ef0a94c6f3c" [[projects]] branch = "master" + digest = "1:e6338f2518362ff701a556bd76afd90a2168d1c658ec5d1ea1e9c5ef30a7d157" name = "github.com/xeipuuv/gojsonpointer" packages = ["."] - revision = "6fe8760cad3569743d51ddbb243b26f8456742dc" + pruneopts = "" + revision = "4e3ac2762d5f479393488629ee9370b50873b3a6" [[projects]] branch = "master" + digest = "1:604f98a38394d2805a78c462396a4992b93fdd5b7306130add330f1a99ac6b0a" name = "github.com/xeipuuv/gojsonreference" packages = ["."] - revision = "e02fc20de94c78484cd5ffb007f8af96be030a45" + pruneopts = "" + revision = "bd5ef7bd5415a7ac448318e64f11a24cd21e594b" [[projects]] branch = "master" + digest = "1:0dd2250939dcf18c0b1a7b0e364e13b083331f723a6853ff2950a0c4273ff6e2" name = "github.com/xeipuuv/gojsonschema" packages = ["."] - revision = "511d08a359d14c0dd9c4302af52ee9abb6f93c2a" + pruneopts = "" + revision = "6cd6dcbc9e7514bea255a9241665a6c2d0b37fb4" [[projects]] branch = "master" + digest = "1:81daf39130b8efb47ab2b841ee42adedeaaf20ab3675236f577722ae78d37728" name = "github.com/yalp/jsonpath" packages = ["."] - revision = "31a79c7593bb93eb10b163650d4a3e6ca190e4dc" + pruneopts = "" + revision = "5cc68e5049a040829faef3a44c00ec4332f6dec7" [[projects]] + digest = "1:529ed3f98838f69e13761788d0cc71b44e130058fab13bae2ce09f7a176bced4" name = "github.com/yudai/gojsondiff" - packages = [".","formatter"] + packages = [ + ".", + "formatter", + ] + pruneopts = "" revision = "7b1b7adf999dab73a6eb02669c3d82dbb27a3dd6" version = "1.0.0" [[projects]] branch = "master" + digest = "1:9857bb2293f372b2181004d8b62179bbdb4ab0982ec6f762abe6cf2bfedaff85" name = "github.com/yudai/golcs" packages = ["."] + pruneopts = "" revision = "ecda9a501e8220fae3b4b600c3db4b0ba22cfc68" [[projects]] branch = "master" + digest = "1:4cae11053a5fc8e7b08228fcc14d161d3e60b64ba508a8b216937da472690991" name = "golang.org/x/crypto" - packages = ["acme","acme/autocert","bcrypt","blowfish","ed25519","ed25519/internal/edwards25519","ssh/terminal"] - revision = "a6600008915114d9c087fad9f03d75087b1a74df" + packages = [ + "acme", + "acme/autocert", + "bcrypt", + "blowfish", + "ed25519", + "ed25519/internal/edwards25519", + "ssh/terminal", + ] + pruneopts = "" + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] branch = "master" + digest = "1:67c2d940f2d5c017ef88e9847709dca9b38d5fe82f1e33fb42ace515219f22f1" name = "golang.org/x/net" - packages = ["bpf","idna","internal/iana","internal/socket","ipv4","ipv6","publicsuffix"] - revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" + packages = [ + "bpf", + "idna", + "internal/iana", + "internal/socket", + "ipv4", + "ipv6", + "publicsuffix", + ] + pruneopts = "" + revision = "f9ce57c11b242f0f1599cf25c89d8cb02c45295a" [[projects]] branch = "master" + digest = "1:8812fbc18f45708b5580ed61267fefe5eeb29b36773bdfaad48b0843e3810c02" name = "golang.org/x/sys" - packages = ["unix","windows"] - revision = "af50095a40f9041b3b38960738837185c26e9419" + packages = [ + "unix", + "windows", + ] + pruneopts = "" + revision = "f0d5e33068cb57c22a181f5df0ffda885309eb5a" [[projects]] - branch = "master" + digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] - revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "" + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" [[projects]] + digest = "1:4014584c076f25aaf35d9de36c79ae2d208bba32c780f405e3395dad79292e22" name = "gopkg.in/DATA-DOG/go-sqlmock.v1" packages = ["."] + pruneopts = "" revision = "d76b18b42f285b792bf985118980ce9eacea9d10" version = "v1.3.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "991ecc43a6e9bcfe3c39169d7509ee821076b0b75bbf7cb38ec06db3041cd009" + input-imports = [ + "github.com/BurntSushi/toml", + "github.com/erikstmartin/go-testdb", + "github.com/gavv/httpexpect", + "github.com/google/uuid", + "github.com/julienschmidt/httprouter", + "github.com/lib/pq", + "github.com/mattn/go-sqlite3", + "github.com/miekg/dns", + "github.com/rs/cors", + "github.com/sirupsen/logrus", + "github.com/sirupsen/logrus/hooks/test", + "github.com/valyala/fasthttp", + "golang.org/x/crypto/acme/autocert", + "golang.org/x/crypto/bcrypt", + "gopkg.in/DATA-DOG/go-sqlmock.v1", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 8e69ffd..9dd4aef 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -59,10 +59,6 @@ required = ["github.com/valyala/fasthttp"] name = "github.com/rs/cors" version = "1.2.0" -[[constraint]] - name = "github.com/satori/go.uuid" - version = "1.2.0" - [[constraint]] name = "github.com/sirupsen/logrus" version = "1.0.4" diff --git a/acmetxt.go b/acmetxt.go index 95719d1..cec7176 100644 --- a/acmetxt.go +++ b/acmetxt.go @@ -4,7 +4,7 @@ import ( "encoding/json" "net" - "github.com/satori/go.uuid" + "github.com/google/uuid" log "github.com/sirupsen/logrus" ) @@ -76,8 +76,8 @@ func (a ACMETxt) allowedFromList(ips []string) bool { func newACMETxt() ACMETxt { var a = ACMETxt{} password := generatePassword(40) - a.Username = uuid.NewV4() + a.Username = uuid.New() a.Password = password - a.Subdomain = uuid.NewV4().String() + a.Subdomain = uuid.New().String() return a } diff --git a/api_test.go b/api_test.go index 3338447..bd359f2 100644 --- a/api_test.go +++ b/api_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/gavv/httpexpect" + "github.com/google/uuid" "github.com/julienschmidt/httprouter" "github.com/rs/cors" - "github.com/satori/go.uuid" "gopkg.in/DATA-DOG/go-sqlmock.v1" ) @@ -25,7 +25,7 @@ func noAuth(update httprouter.Handle) httprouter.Handle { dec := json.NewDecoder(r.Body) _ = dec.Decode(&postData) // Set user info to the decoded ACMETxt object - postData.Username, _ = uuid.FromString(uname) + postData.Username, _ = uuid.Parse(uname) postData.Password = passwd // Set the ACMETxt struct to context to pull in from update function ctx := r.Context() diff --git a/db.go b/db.go index d245808..36b5706 100644 --- a/db.go +++ b/db.go @@ -9,9 +9,9 @@ import ( "strconv" "time" + "github.com/google/uuid" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" - "github.com/satori/go.uuid" log "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" ) diff --git a/types.go b/types.go index c2a6e3b..a615a59 100644 --- a/types.go +++ b/types.go @@ -2,9 +2,10 @@ package main import ( "database/sql" - "github.com/miekg/dns" - "github.com/satori/go.uuid" "sync" + + "github.com/google/uuid" + "github.com/miekg/dns" ) // Config is global configuration struct diff --git a/validation.go b/validation.go index 66e1626..797e763 100644 --- a/validation.go +++ b/validation.go @@ -3,12 +3,12 @@ package main import ( "unicode/utf8" - "github.com/satori/go.uuid" + "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) func getValidUsername(u string) (uuid.UUID, error) { - uname, err := uuid.FromString(u) + uname, err := uuid.Parse(u) if err != nil { return uuid.UUID{}, err } @@ -25,7 +25,7 @@ func validKey(k string) bool { } func validSubdomain(s string) bool { - _, err := uuid.FromString(s) + _, err := uuid.Parse(s) if err == nil { return true } diff --git a/validation_test.go b/validation_test.go index fd63cf4..37dd05f 100644 --- a/validation_test.go +++ b/validation_test.go @@ -1,12 +1,13 @@ package main import ( - "github.com/satori/go.uuid" "testing" + + "github.com/google/uuid" ) func TestGetValidUsername(t *testing.T) { - v1, _ := uuid.FromString("a097455b-52cc-4569-90c8-7a4b97c6eba8") + v1, _ := uuid.Parse("a097455b-52cc-4569-90c8-7a4b97c6eba8") for i, test := range []struct { uname string output uuid.UUID diff --git a/vendor/github.com/gavv/httpexpect/.gometalinter b/vendor/github.com/gavv/httpexpect/.gometalinter index f0869ba..b51dbaf 100644 --- a/vendor/github.com/gavv/httpexpect/.gometalinter +++ b/vendor/github.com/gavv/httpexpect/.gometalinter @@ -5,14 +5,12 @@ "gotype", "goimports", "golint", - "gosimple", "gofmt", "vet", "lll", - "staticcheck", + "megacheck", "ineffassign", "deadcode", - "unused", "unconvert", "misspell", "test", diff --git a/vendor/github.com/gavv/httpexpect/.travis.yml b/vendor/github.com/gavv/httpexpect/.travis.yml index c8a6f6a..6c09971 100644 --- a/vendor/github.com/gavv/httpexpect/.travis.yml +++ b/vendor/github.com/gavv/httpexpect/.travis.yml @@ -2,8 +2,7 @@ language: go sudo: false go: - - 1.7 - - 1.8 + - 1.10.x before_install: - go get golang.org/x/tools/cmd/cover diff --git a/vendor/github.com/gavv/httpexpect/value_test.go b/vendor/github.com/gavv/httpexpect/value_test.go index a912153..1505e90 100644 --- a/vendor/github.com/gavv/httpexpect/value_test.go +++ b/vendor/github.com/gavv/httpexpect/value_test.go @@ -411,6 +411,207 @@ func TestValuePathError(t *testing.T) { } } +// based on github.com/yalp/jsonpath +func TestValuePathExpressions(t *testing.T) { + data := map[string]interface{}{ + "A": []interface{}{ + "string", + 23.3, + 3.0, + true, + false, + nil, + }, + "B": "value", + "C": 3.14, + "D": map[string]interface{}{ + "C": 3.1415, + "V": []interface{}{ + "string2a", + "string2b", + map[string]interface{}{ + "C": 3.141592, + }, + }, + }, + "E": map[string]interface{}{ + "A": []interface{}{"string3"}, + "D": map[string]interface{}{ + "V": map[string]interface{}{ + "C": 3.14159265, + }, + }, + }, + "F": map[string]interface{}{ + "V": []interface{}{ + "string4a", + "string4b", + map[string]interface{}{ + "CC": 3.1415926535, + }, + map[string]interface{}{ + "CC": "hello", + }, + []interface{}{ + "string5a", + "string5b", + }, + []interface{}{ + "string6a", + "string6b", + }, + }, + }, + } + + reporter := newMockReporter(t) + + runTests := func(tests map[string]interface{}) { + value := NewValue(reporter, data) + value.chain.assertOK(t) + + for path, expected := range tests { + actual := value.Path(path) + actual.chain.assertOK(t) + + assert.Equal(t, expected, actual.Raw()) + } + } + + t.Run("pick", func(t *testing.T) { + runTests(map[string]interface{}{ + "$": data, + "$.A[0]": "string", + `$["A"][0]`: "string", + "$.A": []interface{}{"string", 23.3, 3.0, true, false, nil}, + "$.A[*]": []interface{}{"string", 23.3, 3.0, true, false, nil}, + "$.A.*": []interface{}{"string", 23.3, 3.0, true, false, nil}, + "$.A.*.a": []interface{}{}, + }) + }) + + t.Run("slice", func(t *testing.T) { + runTests(map[string]interface{}{ + "$.A[1,4,2]": []interface{}{23.3, false, 3.0}, + `$["B","C"]`: []interface{}{"value", 3.14}, + `$["C","B"]`: []interface{}{3.14, "value"}, + "$.A[1:4]": []interface{}{23.3, 3.0, true}, + "$.A[::2]": []interface{}{"string", 3.0, false}, + "$.A[-2:]": []interface{}{false, nil}, + "$.A[:-1]": []interface{}{"string", 23.3, 3.0, true, false}, + "$.A[::-1]": []interface{}{nil, false, true, 3.0, 23.3, "string"}, + "$.F.V[4:5][0,1]": []interface{}{"string5a", "string5b"}, + "$.F.V[4:6][1]": []interface{}{"string5b", "string6b"}, + "$.F.V[4:6][0,1]": []interface{}{"string5a", "string5b", "string6a", "string6b"}, + "$.F.V[4,5][0:2]": []interface{}{"string5a", "string5b", "string6a", "string6b"}, + "$.F.V[4:6]": []interface{}{ + []interface{}{ + "string5a", + "string5b", + }, + []interface{}{ + "string6a", + "string6b", + }, + }, + }) + }) + + t.Run("quote", func(t *testing.T) { + runTests(map[string]interface{}{ + `$[A][0]`: "string", + `$["A"][0]`: "string", + `$[B,C]`: []interface{}{"value", 3.14}, + `$["B","C"]`: []interface{}{"value", 3.14}, + }) + }) + + t.Run("search", func(t *testing.T) { + runTests(map[string]interface{}{ + "$..C": []interface{}{3.14, 3.1415, 3.141592, 3.14159265}, + `$..["C"]`: []interface{}{3.14, 3.1415, 3.141592, 3.14159265}, + "$.D.V..C": []interface{}{3.141592}, + "$.D.V.*.C": []interface{}{3.141592}, + "$.D.V..*.C": []interface{}{3.141592}, + "$.D.*..C": []interface{}{3.141592}, + "$.*.V..C": []interface{}{3.141592}, + "$.*.D.V.C": []interface{}{3.14159265}, + "$.*.D..C": []interface{}{3.14159265}, + "$.*.D.V..*": []interface{}{3.14159265}, + "$..D..V..C": []interface{}{3.141592, 3.14159265}, + "$.*.*.*.C": []interface{}{3.141592, 3.14159265}, + "$..V..C": []interface{}{3.141592, 3.14159265}, + "$.D.V..*": []interface{}{ + "string2a", + "string2b", + map[string]interface{}{ + "C": 3.141592, + }, + 3.141592, + }, + "$..A": []interface{}{ + []interface{}{"string", 23.3, 3.0, true, false, nil}, + []interface{}{"string3"}, + }, + "$..A..*": []interface{}{"string", 23.3, 3.0, true, false, nil, "string3"}, + "$.A..*": []interface{}{"string", 23.3, 3.0, true, false, nil}, + "$.A.*": []interface{}{"string", 23.3, 3.0, true, false, nil}, + "$..A[0,1]": []interface{}{"string", 23.3}, + "$..A[0]": []interface{}{"string", "string3"}, + "$.*.V[0]": []interface{}{"string2a", "string4a"}, + "$.*.V[1]": []interface{}{"string2b", "string4b"}, + "$.*.V[0,1]": []interface{}{"string2a", "string2b", "string4a", "string4b"}, + "$.*.V[0:2]": []interface{}{"string2a", "string2b", "string4a", "string4b"}, + "$.*.V[2].C": []interface{}{3.141592}, + "$..V[2].C": []interface{}{3.141592}, + "$..V[*].C": []interface{}{3.141592}, + "$.*.V[2].*": []interface{}{3.141592, 3.1415926535}, + "$.*.V[2:3].*": []interface{}{3.141592, 3.1415926535}, + "$.*.V[2:4].*": []interface{}{3.141592, 3.1415926535, "hello"}, + "$..V[2,3].CC": []interface{}{3.1415926535, "hello"}, + "$..V[2:4].CC": []interface{}{3.1415926535, "hello"}, + "$..V[*].*": []interface{}{ + 3.141592, + 3.1415926535, + "hello", + "string5a", + "string5b", + "string6a", + "string6b", + }, + "$..[0]": []interface{}{ + "string", + "string2a", + "string3", + "string4a", + "string5a", + "string6a", + }, + "$..ZZ": []interface{}{}, + }) + }) +} + +func TestValuePathIntFloat(t *testing.T) { + reporter := newMockReporter(t) + + data := map[string]interface{}{ + "A": 123, + "B": 123.0, + } + + value := NewValue(reporter, data) + value.chain.assertOK(t) + + a := value.Path(`$["A"]`) + a.chain.assertOK(t) + assert.Equal(t, 123.0, a.Raw()) + + b := value.Path(`$["B"]`) + b.chain.assertOK(t) + assert.Equal(t, 123.0, b.Raw()) +} + func TestValueSchema(t *testing.T) { reporter := newMockReporter(t) diff --git a/vendor/github.com/google/uuid/.travis.yml b/vendor/github.com/google/uuid/.travis.yml new file mode 100644 index 0000000..d8156a6 --- /dev/null +++ b/vendor/github.com/google/uuid/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4.3 + - 1.5.3 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md new file mode 100644 index 0000000..04fdf09 --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# How to contribute + +We definitely welcome patches and contribution to this project! + +### Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +You may have already signed it for other Google projects. diff --git a/vendor/github.com/google/uuid/CONTRIBUTORS b/vendor/github.com/google/uuid/CONTRIBUTORS new file mode 100644 index 0000000..b4bb97f --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTORS @@ -0,0 +1,9 @@ +Paul Borman +bmatsuo +shawnps +theory +jboverfelt +dsymonds +cd1 +wallclockbuilder +dansouza diff --git a/vendor/github.com/klauspost/crc32/LICENSE b/vendor/github.com/google/uuid/LICENSE similarity index 94% rename from vendor/github.com/klauspost/crc32/LICENSE rename to vendor/github.com/google/uuid/LICENSE index 4fd5963..5dc6826 100644 --- a/vendor/github.com/klauspost/crc32/LICENSE +++ b/vendor/github.com/google/uuid/LICENSE @@ -1,5 +1,4 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2015 Klaus Post +Copyright (c) 2009,2014 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md new file mode 100644 index 0000000..21205ea --- /dev/null +++ b/vendor/github.com/google/uuid/README.md @@ -0,0 +1,23 @@ +**This package is currently in development and the API may not be stable.** + +The API will become stable with v1. + +# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) +The uuid package generates and inspects UUIDs based on +[RFC 4122](http://tools.ietf.org/html/rfc4122) +and DCE 1.1: Authentication and Security Services. + +This package is based on the github.com/pborman/uuid package (previously named +code.google.com/p/go-uuid). It differs from these earlier packages in that +a UUID is a 16 byte array rather than a byte slice. One loss due to this +change is the ability to represent an invalid UUID (vs a NIL UUID). + +###### Install +`go get github.com/google/uuid` + +###### Documentation +[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) + +Full `go doc` style documentation for the package can be viewed online without +installing this package by using the GoDoc site here: +http://godoc.org/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go new file mode 100644 index 0000000..a6479db --- /dev/null +++ b/vendor/github.com/google/uuid/dce.go @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "fmt" + "os" +) + +// A Domain represents a Version 2 domain +type Domain byte + +// Domain constants for DCE Security (Version 2) UUIDs. +const ( + Person = Domain(0) + Group = Domain(1) + Org = Domain(2) +) + +// NewDCESecurity returns a DCE Security (Version 2) UUID. +// +// The domain should be one of Person, Group or Org. +// On a POSIX system the id should be the users UID for the Person +// domain and the users GID for the Group. The meaning of id for +// the domain Org or on non-POSIX systems is site defined. +// +// For a given domain/id pair the same token may be returned for up to +// 7 minutes and 10 seconds. +func NewDCESecurity(domain Domain, id uint32) (UUID, error) { + uuid, err := NewUUID() + if err == nil { + uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 + uuid[9] = byte(domain) + binary.BigEndian.PutUint32(uuid[0:], id) + } + return uuid, err +} + +// NewDCEPerson returns a DCE Security (Version 2) UUID in the person +// domain with the id returned by os.Getuid. +// +// NewDCEPerson(Person, uint32(os.Getuid())) +func NewDCEPerson() (UUID, error) { + return NewDCESecurity(Person, uint32(os.Getuid())) +} + +// NewDCEGroup returns a DCE Security (Version 2) UUID in the group +// domain with the id returned by os.Getgid. +// +// NewDCEGroup(Group, uint32(os.Getgid())) +func NewDCEGroup() (UUID, error) { + return NewDCESecurity(Group, uint32(os.Getgid())) +} + +// Domain returns the domain for a Version 2 UUID. Domains are only defined +// for Version 2 UUIDs. +func (uuid UUID) Domain() Domain { + return Domain(uuid[9]) +} + +// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2 +// UUIDs. +func (uuid UUID) ID() uint32 { + return binary.BigEndian.Uint32(uuid[0:4]) +} + +func (d Domain) String() string { + switch d { + case Person: + return "Person" + case Group: + return "Group" + case Org: + return "Org" + } + return fmt.Sprintf("Domain%d", int(d)) +} diff --git a/vendor/github.com/google/uuid/doc.go b/vendor/github.com/google/uuid/doc.go new file mode 100644 index 0000000..5b8a4b9 --- /dev/null +++ b/vendor/github.com/google/uuid/doc.go @@ -0,0 +1,12 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package uuid generates and inspects UUIDs. +// +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to +// maps or compared directly. +package uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go new file mode 100644 index 0000000..4fc5a77 --- /dev/null +++ b/vendor/github.com/google/uuid/hash.go @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "crypto/md5" + "crypto/sha1" + "hash" +) + +// Well known namespace IDs and UUIDs +var ( + NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) + Nil UUID // empty UUID, all zeros +) + +// NewHash returns a new UUID derived from the hash of space concatenated with +// data generated by h. The hash should be at least 16 byte in length. The +// first 16 bytes of the hash are used to form the UUID. The version of the +// UUID will be the lower 4 bits of version. NewHash is used to implement +// NewMD5 and NewSHA1. +func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { + h.Reset() + h.Write(space[:]) + h.Write([]byte(data)) + s := h.Sum(nil) + var uuid UUID + copy(uuid[:], s) + uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant + return uuid +} + +// NewMD5 returns a new MD5 (Version 3) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(md5.New(), space, data, 3) +func NewMD5(space UUID, data []byte) UUID { + return NewHash(md5.New(), space, data, 3) +} + +// NewSHA1 returns a new SHA1 (Version 5) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(sha1.New(), space, data, 5) +func NewSHA1(space UUID, data []byte) UUID { + return NewHash(sha1.New(), space, data, 5) +} diff --git a/vendor/github.com/google/uuid/json_test.go b/vendor/github.com/google/uuid/json_test.go new file mode 100644 index 0000000..245f91e --- /dev/null +++ b/vendor/github.com/google/uuid/json_test.go @@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/json" + "reflect" + "testing" +) + +var testUUID = Must(Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")) + +func TestJSON(t *testing.T) { + type S struct { + ID1 UUID + ID2 UUID + } + s1 := S{ID1: testUUID} + data, err := json.Marshal(&s1) + if err != nil { + t.Fatal(err) + } + var s2 S + if err := json.Unmarshal(data, &s2); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(&s1, &s2) { + t.Errorf("got %#v, want %#v", s2, s1) + } +} + +func BenchmarkUUID_MarshalJSON(b *testing.B) { + x := &struct { + UUID UUID `json:"uuid"` + }{} + var err error + x.UUID, err = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + if err != nil { + b.Fatal(err) + } + for i := 0; i < b.N; i++ { + js, err := json.Marshal(x) + if err != nil { + b.Fatalf("marshal json: %#v (%v)", js, err) + } + } +} + +func BenchmarkUUID_UnmarshalJSON(b *testing.B) { + js := []byte(`{"uuid":"f47ac10b-58cc-0372-8567-0e02b2c3d479"}`) + var x *struct { + UUID UUID `json:"uuid"` + } + for i := 0; i < b.N; i++ { + err := json.Unmarshal(js, &x) + if err != nil { + b.Fatalf("marshal json: %#v (%v)", js, err) + } + } +} diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go new file mode 100644 index 0000000..84bbc58 --- /dev/null +++ b/vendor/github.com/google/uuid/marshal.go @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "fmt" + +// MarshalText implements encoding.TextMarshaler. +func (uuid UUID) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], uuid) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (uuid *UUID) UnmarshalText(data []byte) error { + // See comment in ParseBytes why we do this. + // id, err := ParseBytes(data) + id, err := ParseBytes(data) + if err == nil { + *uuid = id + } + return err +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (uuid UUID) MarshalBinary() ([]byte, error) { + return uuid[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (uuid *UUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(uuid[:], data) + return nil +} diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go new file mode 100644 index 0000000..5f0156a --- /dev/null +++ b/vendor/github.com/google/uuid/node.go @@ -0,0 +1,103 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "net" + "sync" +) + +var ( + nodeMu sync.Mutex + interfaces []net.Interface // cached list of interfaces + ifname string // name of interface being used + nodeID [6]byte // hardware for version 1 UUIDs + zeroID [6]byte // nodeID with only 0's +) + +// NodeInterface returns the name of the interface from which the NodeID was +// derived. The interface "user" is returned if the NodeID was set by +// SetNodeID. +func NodeInterface() string { + defer nodeMu.Unlock() + nodeMu.Lock() + return ifname +} + +// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. +// If name is "" then the first usable interface found will be used or a random +// Node ID will be generated. If a named interface cannot be found then false +// is returned. +// +// SetNodeInterface never fails when name is "". +func SetNodeInterface(name string) bool { + defer nodeMu.Unlock() + nodeMu.Lock() + return setNodeInterface(name) +} + +func setNodeInterface(name string) bool { + if interfaces == nil { + var err error + interfaces, err = net.Interfaces() + if err != nil && name != "" { + return false + } + } + + for _, ifs := range interfaces { + if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { + copy(nodeID[:], ifs.HardwareAddr) + ifname = ifs.Name + return true + } + } + + // We found no interfaces with a valid hardware address. If name + // does not specify a specific interface generate a random Node ID + // (section 4.1.6) + if name == "" { + randomBits(nodeID[:]) + return true + } + return false +} + +// NodeID returns a slice of a copy of the current Node ID, setting the Node ID +// if not already set. +func NodeID() []byte { + defer nodeMu.Unlock() + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nid := nodeID + return nid[:] +} + +// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes +// of id are used. If id is less than 6 bytes then false is returned and the +// Node ID is not set. +func SetNodeID(id []byte) bool { + if len(id) < 6 { + return false + } + defer nodeMu.Unlock() + nodeMu.Lock() + copy(nodeID[:], id) + ifname = "user" + return true +} + +// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is +// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) NodeID() []byte { + if len(uuid) != 16 { + return nil + } + var node [6]byte + copy(node[:], uuid[10:]) + return node[:] +} diff --git a/vendor/github.com/google/uuid/seq_test.go b/vendor/github.com/google/uuid/seq_test.go new file mode 100644 index 0000000..853a4aa --- /dev/null +++ b/vendor/github.com/google/uuid/seq_test.go @@ -0,0 +1,66 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "flag" + "runtime" + "testing" + "time" +) + +// This test is only run when --regressions is passed on the go test line. +var regressions = flag.Bool("regressions", false, "run uuid regression tests") + +// TestClockSeqRace tests for a particular race condition of returning two +// identical Version1 UUIDs. The duration of 1 minute was chosen as the race +// condition, before being fixed, nearly always occured in under 30 seconds. +func TestClockSeqRace(t *testing.T) { + if !*regressions { + t.Skip("skipping regression tests") + } + duration := time.Minute + + done := make(chan struct{}) + defer close(done) + + ch := make(chan UUID, 10000) + ncpu := runtime.NumCPU() + switch ncpu { + case 0, 1: + // We can't run the test effectively. + t.Skip("skipping race test, only one CPU detected") + return + default: + runtime.GOMAXPROCS(ncpu) + } + for i := 0; i < ncpu; i++ { + go func() { + for { + select { + case <-done: + return + case ch <- Must(NewUUID()): + } + } + }() + } + + uuids := make(map[string]bool) + cnt := 0 + start := time.Now() + for u := range ch { + s := u.String() + if uuids[s] { + t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s) + return + } + uuids[s] = true + if time.Since(start) > duration { + return + } + cnt++ + } +} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go new file mode 100644 index 0000000..528ad0d --- /dev/null +++ b/vendor/github.com/google/uuid/sql.go @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements sql.Scanner so UUIDs can be read from databases transparently +// Currently, database types that map to string and []byte are supported. Please +// consult database-specific driver documentation for matching types. +func (uuid *UUID) Scan(src interface{}) error { + switch src.(type) { + case string: + // if an empty UUID comes from a table, we return a null UUID + if src.(string) == "" { + return nil + } + + // see Parse for required string format + u, err := Parse(src.(string)) + + if err != nil { + return fmt.Errorf("Scan: %v", err) + } + + *uuid = u + case []byte: + b := src.([]byte) + + // if an empty UUID comes from a table, we return a null UUID + if len(b) == 0 { + return nil + } + + // assumes a simple slice of bytes if 16 bytes + // otherwise attempts to parse + if len(b) != 16 { + return uuid.Scan(string(b)) + } + copy((*uuid)[:], b) + + default: + return fmt.Errorf("Scan: unable to scan type %T into UUID", src) + } + + return nil +} + +// Value implements sql.Valuer so that UUIDs can be written to databases +// transparently. Currently, UUIDs map to strings. Please consult +// database-specific driver documentation for matching types. +func (uuid UUID) Value() (driver.Value, error) { + return uuid.String(), nil +} diff --git a/vendor/github.com/google/uuid/sql_test.go b/vendor/github.com/google/uuid/sql_test.go new file mode 100644 index 0000000..c193196 --- /dev/null +++ b/vendor/github.com/google/uuid/sql_test.go @@ -0,0 +1,102 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "strings" + "testing" +) + +func TestScan(t *testing.T) { + var stringTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d479" + var badTypeTest int = 6 + var invalidTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d4" + + byteTest := make([]byte, 16) + byteTestUUID := Must(Parse(stringTest)) + copy(byteTest, byteTestUUID[:]) + + // sunny day tests + + var uuid UUID + err := (&uuid).Scan(stringTest) + if err != nil { + t.Fatal(err) + } + + err = (&uuid).Scan([]byte(stringTest)) + if err != nil { + t.Fatal(err) + } + + err = (&uuid).Scan(byteTest) + if err != nil { + t.Fatal(err) + } + + // bad type tests + + err = (&uuid).Scan(badTypeTest) + if err == nil { + t.Error("int correctly parsed and shouldn't have") + } + if !strings.Contains(err.Error(), "unable to scan type") { + t.Error("attempting to parse an int returned an incorrect error message") + } + + // invalid/incomplete uuids + + err = (&uuid).Scan(invalidTest) + if err == nil { + t.Error("invalid uuid was parsed without error") + } + if !strings.Contains(err.Error(), "invalid UUID") { + t.Error("attempting to parse an invalid UUID returned an incorrect error message") + } + + err = (&uuid).Scan(byteTest[:len(byteTest)-2]) + if err == nil { + t.Error("invalid byte uuid was parsed without error") + } + if !strings.Contains(err.Error(), "invalid UUID") { + t.Error("attempting to parse an invalid byte UUID returned an incorrect error message") + } + + // empty tests + + uuid = UUID{} + var emptySlice []byte + err = (&uuid).Scan(emptySlice) + if err != nil { + t.Fatal(err) + } + + for _, v := range uuid { + if v != 0 { + t.Error("UUID was not nil after scanning empty byte slice") + } + } + + uuid = UUID{} + var emptyString string + err = (&uuid).Scan(emptyString) + if err != nil { + t.Fatal(err) + } + for _, v := range uuid { + if v != 0 { + t.Error("UUID was not nil after scanning empty byte slice") + } + } +} + +func TestValue(t *testing.T) { + stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479" + uuid := Must(Parse(stringTest)) + val, _ := uuid.Value() + if val != stringTest { + t.Error("Value() did not return expected string") + } +} diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go new file mode 100644 index 0000000..fd7fe0a --- /dev/null +++ b/vendor/github.com/google/uuid/time.go @@ -0,0 +1,123 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "sync" + "time" +) + +// A Time represents a time as the number of 100's of nanoseconds since 15 Oct +// 1582. +type Time int64 + +const ( + lillian = 2299160 // Julian day of 15 Oct 1582 + unix = 2440587 // Julian day of 1 Jan 1970 + epoch = unix - lillian // Days between epochs + g1582 = epoch * 86400 // seconds between epochs + g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs +) + +var ( + timeMu sync.Mutex + lasttime uint64 // last time we returned + clockSeq uint16 // clock sequence for this run + + timeNow = time.Now // for testing +) + +// UnixTime converts t the number of seconds and nanoseconds using the Unix +// epoch of 1 Jan 1970. +func (t Time) UnixTime() (sec, nsec int64) { + sec = int64(t - g1582ns100) + nsec = (sec % 10000000) * 100 + sec /= 10000000 + return sec, nsec +} + +// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and +// clock sequence as well as adjusting the clock sequence as needed. An error +// is returned if the current time cannot be determined. +func GetTime() (Time, uint16, error) { + defer timeMu.Unlock() + timeMu.Lock() + return getTime() +} + +func getTime() (Time, uint16, error) { + t := timeNow() + + // If we don't have a clock sequence already, set one. + if clockSeq == 0 { + setClockSequence(-1) + } + now := uint64(t.UnixNano()/100) + g1582ns100 + + // If time has gone backwards with this clock sequence then we + // increment the clock sequence + if now <= lasttime { + clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 + } + lasttime = now + return Time(now), clockSeq, nil +} + +// ClockSequence returns the current clock sequence, generating one if not +// already set. The clock sequence is only used for Version 1 UUIDs. +// +// The uuid package does not use global static storage for the clock sequence or +// the last time a UUID was generated. Unless SetClockSequence is used, a new +// random clock sequence is generated the first time a clock sequence is +// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) +func ClockSequence() int { + defer timeMu.Unlock() + timeMu.Lock() + return clockSequence() +} + +func clockSequence() int { + if clockSeq == 0 { + setClockSequence(-1) + } + return int(clockSeq & 0x3fff) +} + +// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to +// -1 causes a new sequence to be generated. +func SetClockSequence(seq int) { + defer timeMu.Unlock() + timeMu.Lock() + setClockSequence(seq) +} + +func setClockSequence(seq int) { + if seq == -1 { + var b [2]byte + randomBits(b[:]) // clock sequence + seq = int(b[0])<<8 | int(b[1]) + } + old_seq := clockSeq + clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant + if old_seq != clockSeq { + lasttime = 0 + } +} + +// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in +// uuid. The time is only defined for version 1 and 2 UUIDs. +func (uuid UUID) Time() Time { + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + return Time(time) +} + +// ClockSequence returns the clock sequence encoded in uuid. +// The clock sequence is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) ClockSequence() int { + return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff +} diff --git a/vendor/github.com/google/uuid/util.go b/vendor/github.com/google/uuid/util.go new file mode 100644 index 0000000..5ea6c73 --- /dev/null +++ b/vendor/github.com/google/uuid/util.go @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// randomBits completely fills slice b with random data. +func randomBits(b []byte) { + if _, err := io.ReadFull(rander, b); err != nil { + panic(err.Error()) // rand should never fail + } +} + +// xvalues returns the value of a byte as a hexadecimal digit or 255. +var xvalues = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +} + +// xtob converts hex characters x1 and x2 into a byte. +func xtob(x1, x2 byte) (byte, bool) { + b1 := xvalues[x1] + b2 := xvalues[x2] + return (b1 << 4) | b2, b1 != 255 && b2 != 255 +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go new file mode 100644 index 0000000..b7b9ced --- /dev/null +++ b/vendor/github.com/google/uuid/uuid.go @@ -0,0 +1,191 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "strings" +) + +// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC +// 4122. +type UUID [16]byte + +// A Version represents a UUID's version. +type Version byte + +// A Variant represents a UUID's variant. +type Variant byte + +// Constants returned by Variant. +const ( + Invalid = Variant(iota) // Invalid UUID + RFC4122 // The variant specified in RFC4122 + Reserved // Reserved, NCS backward compatibility. + Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future // Reserved for future definition. +) + +var rander = rand.Reader // random function + +// Parse decodes s into a UUID or returns an error. Both the UUID form of +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +func Parse(s string) (UUID, error) { + var uuid UUID + if len(s) != 36 { + if len(s) != 36+9 { + return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) + } + if strings.ToLower(s[:9]) != "urn:uuid:" { + return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + } + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + if v, ok := xtob(s[x], s[x+1]); !ok { + return uuid, errors.New("invalid UUID format") + } else { + uuid[i] = v + } + } + return uuid, nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + var uuid UUID + if len(b) != 36 { + if len(b) != 36+9 { + return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) + } + if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { + return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) + } + b = b[9:] + } + if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + if v, ok := xtob(b[x], b[x+1]); !ok { + return uuid, errors.New("invalid UUID format") + } else { + uuid[i] = v + } + } + return uuid, nil +} + +// Must returns uuid if err is nil and panics otherwise. +func Must(uuid UUID, err error) UUID { + if err != nil { + panic(err) + } + return uuid +} + +// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// , or "" if uuid is invalid. +func (uuid UUID) String() string { + var buf [36]byte + encodeHex(buf[:], uuid) + return string(buf[:]) +} + +// URN returns the RFC 2141 URN form of uuid, +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. +func (uuid UUID) URN() string { + var buf [36 + 9]byte + copy(buf[:], "urn:uuid:") + encodeHex(buf[9:], uuid) + return string(buf[:]) +} + +func encodeHex(dst []byte, uuid UUID) { + hex.Encode(dst[:], uuid[:4]) + dst[8] = '-' + hex.Encode(dst[9:13], uuid[4:6]) + dst[13] = '-' + hex.Encode(dst[14:18], uuid[6:8]) + dst[18] = '-' + hex.Encode(dst[19:23], uuid[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], uuid[10:]) +} + +// Variant returns the variant encoded in uuid. +func (uuid UUID) Variant() Variant { + switch { + case (uuid[8] & 0xc0) == 0x80: + return RFC4122 + case (uuid[8] & 0xe0) == 0xc0: + return Microsoft + case (uuid[8] & 0xe0) == 0xe0: + return Future + default: + return Reserved + } +} + +// Version returns the version of uuid. +func (uuid UUID) Version() Version { + return Version(uuid[6] >> 4) +} + +func (v Version) String() string { + if v > 15 { + return fmt.Sprintf("BAD_VERSION_%d", v) + } + return fmt.Sprintf("VERSION_%d", v) +} + +func (v Variant) String() string { + switch v { + case RFC4122: + return "RFC4122" + case Reserved: + return "Reserved" + case Microsoft: + return "Microsoft" + case Future: + return "Future" + case Invalid: + return "Invalid" + } + return fmt.Sprintf("BadVariant%d", int(v)) +} + +// SetRand sets the random number generator to r, which implents io.Reader. +// If r.Read returns an error when the package requests random data then +// a panic will be issued. +// +// Calling SetRand with nil sets the random number generator to the default +// generator. +func SetRand(r io.Reader) { + if r == nil { + rander = rand.Reader + return + } + rander = r +} diff --git a/vendor/github.com/google/uuid/uuid_test.go b/vendor/github.com/google/uuid/uuid_test.go new file mode 100644 index 0000000..70986ff --- /dev/null +++ b/vendor/github.com/google/uuid/uuid_test.go @@ -0,0 +1,526 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "fmt" + "os" + "strings" + "testing" + "time" + "unsafe" +) + +type test struct { + in string + version Version + variant Variant + isuuid bool +} + +var tests = []test{ + {"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true}, + {"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true}, + {"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true}, + {"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true}, + {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, + {"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true}, + {"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true}, + {"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true}, + {"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true}, + {"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true}, + {"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true}, + {"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true}, + {"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true}, + {"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true}, + {"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true}, + {"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true}, + + {"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, + {"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true}, + {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, + {"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true}, + {"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true}, + {"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true}, + {"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true}, + {"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true}, + {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true}, + {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true}, + + {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false}, + {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false}, + {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false}, + {"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false}, + {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false}, + {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false}, +} + +var constants = []struct { + c interface{} + name string +}{ + {Person, "Person"}, + {Group, "Group"}, + {Org, "Org"}, + {Invalid, "Invalid"}, + {RFC4122, "RFC4122"}, + {Reserved, "Reserved"}, + {Microsoft, "Microsoft"}, + {Future, "Future"}, + {Domain(17), "Domain17"}, + {Variant(42), "BadVariant42"}, +} + +func testTest(t *testing.T, in string, tt test) { + uuid, err := Parse(in) + if ok := (err == nil); ok != tt.isuuid { + t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid) + } + if err != nil { + return + } + + if v := uuid.Variant(); v != tt.variant { + t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant) + } + if v := uuid.Version(); v != tt.version { + t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version) + } +} + +func testBytes(t *testing.T, in []byte, tt test) { + uuid, err := ParseBytes(in) + if ok := (err == nil); ok != tt.isuuid { + t.Errorf("ParseBytes(%s) got %v expected %v\b", in, ok, tt.isuuid) + } + if err != nil { + return + } + suuid, _ := Parse(string(in)) + if uuid != suuid { + t.Errorf("ParseBytes(%s) got %v expected %v\b", in, uuid, suuid) + } +} + +func TestUUID(t *testing.T) { + for _, tt := range tests { + testTest(t, tt.in, tt) + testTest(t, strings.ToUpper(tt.in), tt) + testBytes(t, []byte(tt.in), tt) + } +} + +func TestConstants(t *testing.T) { + for x, tt := range constants { + v, ok := tt.c.(fmt.Stringer) + if !ok { + t.Errorf("%x: %v: not a stringer", x, v) + } else if s := v.String(); s != tt.name { + v, _ := tt.c.(int) + t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name) + } + } +} + +func TestRandomUUID(t *testing.T) { + m := make(map[string]bool) + for x := 1; x < 32; x++ { + uuid := New() + s := uuid.String() + if m[s] { + t.Errorf("NewRandom returned duplicated UUID %s", s) + } + m[s] = true + if v := uuid.Version(); v != 4 { + t.Errorf("Random UUID of version %s", v) + } + if uuid.Variant() != RFC4122 { + t.Errorf("Random UUID is variant %d", uuid.Variant()) + } + } +} + +func TestNew(t *testing.T) { + m := make(map[UUID]bool) + for x := 1; x < 32; x++ { + s := New() + if m[s] { + t.Errorf("New returned duplicated UUID %s", s) + } + m[s] = true + uuid, err := Parse(s.String()) + if err != nil { + t.Errorf("New.String() returned %q which does not decode", s) + continue + } + if v := uuid.Version(); v != 4 { + t.Errorf("Random UUID of version %s", v) + } + if uuid.Variant() != RFC4122 { + t.Errorf("Random UUID is variant %d", uuid.Variant()) + } + } +} + +func TestClockSeq(t *testing.T) { + // Fake time.Now for this test to return a monotonically advancing time; restore it at end. + defer func(orig func() time.Time) { timeNow = orig }(timeNow) + monTime := time.Now() + timeNow = func() time.Time { + monTime = monTime.Add(1 * time.Second) + return monTime + } + + SetClockSequence(-1) + uuid1, err := NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + uuid2, err := NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + + if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 != s2 { + t.Errorf("clock sequence %d != %d", s1, s2) + } + + SetClockSequence(-1) + uuid2, err = NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + + // Just on the very off chance we generated the same sequence + // two times we try again. + if uuid1.ClockSequence() == uuid2.ClockSequence() { + SetClockSequence(-1) + uuid2, err = NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + } + if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 == s2 { + t.Errorf("Duplicate clock sequence %d", s1) + } + + SetClockSequence(0x1234) + uuid1, err = NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + if seq := uuid1.ClockSequence(); seq != 0x1234 { + t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq) + } +} + +func TestCoding(t *testing.T) { + text := "7d444840-9dc0-11d1-b245-5ffdce74fad2" + urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2" + data := UUID{ + 0x7d, 0x44, 0x48, 0x40, + 0x9d, 0xc0, + 0x11, 0xd1, + 0xb2, 0x45, + 0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2, + } + if v := data.String(); v != text { + t.Errorf("%x: encoded to %s, expected %s", data, v, text) + } + if v := data.URN(); v != urn { + t.Errorf("%x: urn is %s, expected %s", data, v, urn) + } + + uuid, err := Parse(text) + if err != nil { + t.Errorf("Parse returned unexpected error %v", err) + } + if data != data { + t.Errorf("%s: decoded to %s, expected %s", text, uuid, data) + } +} + +func TestVersion1(t *testing.T) { + uuid1, err := NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + uuid2, err := NewUUID() + if err != nil { + t.Fatalf("could not create UUID: %v", err) + } + + if uuid1 == uuid2 { + t.Errorf("%s:duplicate uuid", uuid1) + } + if v := uuid1.Version(); v != 1 { + t.Errorf("%s: version %s expected 1", uuid1, v) + } + if v := uuid2.Version(); v != 1 { + t.Errorf("%s: version %s expected 1", uuid2, v) + } + n1 := uuid1.NodeID() + n2 := uuid2.NodeID() + if !bytes.Equal(n1, n2) { + t.Errorf("Different nodes %x != %x", n1, n2) + } + t1 := uuid1.Time() + t2 := uuid2.Time() + q1 := uuid1.ClockSequence() + q2 := uuid2.ClockSequence() + + switch { + case t1 == t2 && q1 == q2: + t.Error("time stopped") + case t1 > t2 && q1 == q2: + t.Error("time reversed") + case t1 < t2 && q1 != q2: + t.Error("clock sequence chaned unexpectedly") + } +} + +func TestNode(t *testing.T) { + // This test is mostly to make sure we don't leave nodeMu locked. + ifname = "" + if ni := NodeInterface(); ni != "" { + t.Errorf("NodeInterface got %q, want %q", ni, "") + } + if SetNodeInterface("xyzzy") { + t.Error("SetNodeInterface succeeded on a bad interface name") + } + if !SetNodeInterface("") { + t.Error("SetNodeInterface failed") + } + if ni := NodeInterface(); ni == "" { + t.Error("NodeInterface returned an empty string") + } + + ni := NodeID() + if len(ni) != 6 { + t.Errorf("ni got %d bytes, want 6", len(ni)) + } + hasData := false + for _, b := range ni { + if b != 0 { + hasData = true + } + } + if !hasData { + t.Error("nodeid is all zeros") + } + + id := []byte{1, 2, 3, 4, 5, 6, 7, 8} + SetNodeID(id) + ni = NodeID() + if !bytes.Equal(ni, id[:6]) { + t.Errorf("got nodeid %v, want %v", ni, id[:6]) + } + + if ni := NodeInterface(); ni != "user" { + t.Errorf("got inteface %q, want %q", ni, "user") + } +} + +func TestNodeAndTime(t *testing.T) { + // Time is February 5, 1998 12:30:23.136364800 AM GMT + + uuid, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2") + if err != nil { + t.Fatalf("Parser returned unexpected error %v", err) + } + node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2} + + ts := uuid.Time() + c := time.Unix(ts.UnixTime()) + want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC) + if !c.Equal(want) { + t.Errorf("Got time %v, want %v", c, want) + } + if !bytes.Equal(node, uuid.NodeID()) { + t.Errorf("Expected node %v got %v", node, uuid.NodeID()) + } +} + +func TestMD5(t *testing.T) { + uuid := NewMD5(NameSpaceDNS, []byte("python.org")).String() + want := "6fa459ea-ee8a-3ca4-894e-db77e160355e" + if uuid != want { + t.Errorf("MD5: got %q expected %q", uuid, want) + } +} + +func TestSHA1(t *testing.T) { + uuid := NewSHA1(NameSpaceDNS, []byte("python.org")).String() + want := "886313e1-3b8a-5372-9b90-0c9aee199e5d" + if uuid != want { + t.Errorf("SHA1: got %q expected %q", uuid, want) + } +} + +func TestNodeID(t *testing.T) { + nid := []byte{1, 2, 3, 4, 5, 6} + SetNodeInterface("") + s := NodeInterface() + if s == "" || s == "user" { + t.Errorf("NodeInterface %q after SetInteface", s) + } + node1 := NodeID() + if node1 == nil { + t.Error("NodeID nil after SetNodeInterface", s) + } + SetNodeID(nid) + s = NodeInterface() + if s != "user" { + t.Errorf("Expected NodeInterface %q got %q", "user", s) + } + node2 := NodeID() + if node2 == nil { + t.Error("NodeID nil after SetNodeID", s) + } + if bytes.Equal(node1, node2) { + t.Error("NodeID not changed after SetNodeID", s) + } else if !bytes.Equal(nid, node2) { + t.Errorf("NodeID is %x, expected %x", node2, nid) + } +} + +func testDCE(t *testing.T, name string, uuid UUID, err error, domain Domain, id uint32) { + if err != nil { + t.Errorf("%s failed: %v", name, err) + return + } + if v := uuid.Version(); v != 2 { + t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v) + return + } + if v := uuid.Domain(); v != domain { + t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v) + } + if v := uuid.ID(); v != id { + t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v) + } +} + +func TestDCE(t *testing.T) { + uuid, err := NewDCESecurity(42, 12345678) + testDCE(t, "NewDCESecurity", uuid, err, 42, 12345678) + uuid, err = NewDCEPerson() + testDCE(t, "NewDCEPerson", uuid, err, Person, uint32(os.Getuid())) + uuid, err = NewDCEGroup() + testDCE(t, "NewDCEGroup", uuid, err, Group, uint32(os.Getgid())) +} + +type badRand struct{} + +func (r badRand) Read(buf []byte) (int, error) { + for i, _ := range buf { + buf[i] = byte(i) + } + return len(buf), nil +} + +func TestBadRand(t *testing.T) { + SetRand(badRand{}) + uuid1 := New() + uuid2 := New() + if uuid1 != uuid2 { + t.Errorf("execpted duplicates, got %q and %q", uuid1, uuid2) + } + SetRand(nil) + uuid1 = New() + uuid2 = New() + if uuid1 == uuid2 { + t.Errorf("unexecpted duplicates, got %q", uuid1) + } +} + +var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479" +var asBytes = []byte(asString) + +func BenchmarkParse(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := Parse(asString) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkParseBytes(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := ParseBytes(asBytes) + if err != nil { + b.Fatal(err) + } + } +} + +// parseBytesUnsafe is to benchmark using unsafe. +func parseBytesUnsafe(b []byte) (UUID, error) { + return Parse(*(*string)(unsafe.Pointer(&b))) +} + + +func BenchmarkParseBytesUnsafe(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := parseBytesUnsafe(asBytes) + if err != nil { + b.Fatal(err) + } + } +} + +// parseBytesCopy is to benchmark not using unsafe. +func parseBytesCopy(b []byte) (UUID, error) { + return Parse(string(b)) +} + +func BenchmarkParseBytesCopy(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := parseBytesCopy(asBytes) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkNew(b *testing.B) { + for i := 0; i < b.N; i++ { + New() + } +} + +func BenchmarkUUID_String(b *testing.B) { + uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + if err != nil { + b.Fatal(err) + } + for i := 0; i < b.N; i++ { + if uuid.String() == "" { + b.Fatal("invalid uuid") + } + } +} + +func BenchmarkUUID_URN(b *testing.B) { + uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + if err != nil { + b.Fatal(err) + } + for i := 0; i < b.N; i++ { + if uuid.URN() == "" { + b.Fatal("invalid uuid") + } + } +} diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go new file mode 100644 index 0000000..22dc07c --- /dev/null +++ b/vendor/github.com/google/uuid/version1.go @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" +) + +// NewUUID returns a Version 1 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewUUID returns nil. If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewUUID returns Nil and an error. +// +// In most cases, New should be used. +func NewUUID() (UUID, error) { + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nodeMu.Unlock() + + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + timeLow := uint32(now & 0xffffffff) + timeMid := uint16((now >> 32) & 0xffff) + timeHi := uint16((now >> 48) & 0x0fff) + timeHi |= 0x1000 // Version 1 + + binary.BigEndian.PutUint32(uuid[0:], timeLow) + binary.BigEndian.PutUint16(uuid[4:], timeMid) + binary.BigEndian.PutUint16(uuid[6:], timeHi) + binary.BigEndian.PutUint16(uuid[8:], seq) + copy(uuid[10:], nodeID[:]) + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go new file mode 100644 index 0000000..390dd2c --- /dev/null +++ b/vendor/github.com/google/uuid/version4.go @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "io" + +// New is creates a new random UUID or panics. New is equivalent to +// the expression +// +// uuid.Must(uuid.NewRandom()) +func New() UUID { + return Must(NewRandom()) +} + +// NewRandom returns a Random (Version 4) UUID or panics. +// +// The strength of the UUIDs is based on the strength of the crypto/rand +// package. +// +// A note about uniqueness derived from from the UUID Wikipedia entry: +// +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. +func NewRandom() (UUID, error) { + var uuid UUID + _, err := io.ReadFull(rander, uuid[:]) + if err != nil { + return Nil, err + } + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/klauspost/compress/.gitattributes b/vendor/github.com/klauspost/compress/.gitattributes new file mode 100644 index 0000000..e1c269d --- /dev/null +++ b/vendor/github.com/klauspost/compress/.gitattributes @@ -0,0 +1 @@ +*.bin -text -diff diff --git a/vendor/github.com/klauspost/compress/.travis.yml b/vendor/github.com/klauspost/compress/.travis.yml index 182d38a..00557ce 100644 --- a/vendor/github.com/klauspost/compress/.travis.yml +++ b/vendor/github.com/klauspost/compress/.travis.yml @@ -1,24 +1,27 @@ -language: go - -sudo: false - -os: - - linux - - osx - -go: - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - tip - -install: - - go get -t ./... - -script: - - diff <(gofmt -d .) <(printf "") - - go test -v -cpu=2 ./... - - go test -cpu=2 -tags=noasm ./... - - go test -cpu=1,2,4 -short -race ./... - - go test -cpu=2,4 -short -race -tags=noasm ./... +language: go + +sudo: false + +os: + - linux + - osx + +go: + - 1.9.x + - 1.10.x + - master + +install: + - go get -t ./... + +script: + - diff <(gofmt -d .) <(printf "") + - go test -v -cpu=2 ./... + - go test -cpu=2 -tags=noasm ./... + - go test -cpu=1,2,4 -short -race ./... + - go test -cpu=2,4 -short -race -tags=noasm ./... + +matrix: + allow_failures: + - go: 'master' + fast_finish: true diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 25c8e2b..90f2407 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -10,9 +10,18 @@ It offers slightly better compression at lower compression settings, and up to 3 * [Re-balancing Deflate Compression Levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/) [![Build Status](https://travis-ci.org/klauspost/compress.svg?branch=master)](https://travis-ci.org/klauspost/compress) +[![Sourcegraph Badge](https://sourcegraph.com/github.com/klauspost/compress/-/badge.svg)](https://sourcegraph.com/github.com/klauspost/compress?badge) # changelog -* Jan 14, 2017: Reduce stack pressure due to array copies. See [Issue #18625(https://github.com/golang/go/issues/18625). + +* Jul 8, 2018: Added [Performance Update 2018](#performance-update-2018) below. +* Jun 23, 2018: Merged [Go 1.11 inflate optimizations](https://go-review.googlesource.com/c/go/+/102235). Go 1.9 is now required. Backwards compatible version tagged with [v1.3.0](https://github.com/klauspost/compress/releases/tag/v1.3.0). +* Apr 2, 2018: Added [huff0](https://godoc.org/github.com/klauspost/compress/huff0) en/decoder. Experimental for now, API may change. +* Mar 4, 2018: Added [FSE Entropy](https://godoc.org/github.com/klauspost/compress/fse) en/decoder. Experimental for now, API may change. +* Nov 3, 2017: Add compression [Estimate](https://godoc.org/github.com/klauspost/compress#Estimate) function. +* May 28, 2017: Reduce allocations when resetting decoder. +* Apr 02, 2017: Change back to official crc32, since changes were merged in Go 1.7. +* Jan 14, 2017: Reduce stack pressure due to array copies. See [Issue #18625](https://github.com/golang/go/issues/18625). * Oct 25, 2016: Level 2-4 have been rewritten and now offers significantly better performance than before. * Oct 20, 2016: Port zlib changes from Go 1.7 to fix zlib writer issue. Please update. * Oct 16, 2016: Go 1.7 changes merged. Apples to apples this package is a few percent faster, but has a significantly better balance between speed and compression per level. @@ -50,7 +59,7 @@ The packages are drop-in replacements for standard libraries. Simply replace the | `compress/gzip` | `github.com/klauspost/compress/gzip` | | `compress/zlib` | `github.com/klauspost/compress/zlib` | | `archive/zip` | `github.com/klauspost/compress/zip` | -| `compress/deflate` | `github.com/klauspost/compress/deflate` | +| `compress/flate` | `github.com/klauspost/compress/flate` | You may also be interested in [pgzip](https://github.com/klauspost/pgzip), which is a drop in replacement for gzip, which support multithreaded compression on big files and the optimized [crc32](https://github.com/klauspost/crc32) package used by these packages. @@ -58,151 +67,72 @@ The packages contains the same as the standard library, so you can use the godoc Currently there is only minor speedup on decompression (mostly CRC32 calculation). -# deflate optimizations +# Performance Update 2018 -* Minimum matches are 4 bytes, this leads to fewer searches and better compression. (In Go 1.7) -* Stronger hash (iSCSI CRC32) for matches on x64 with SSE 4.2 support. This leads to fewer hash collisions. (Go 1.7 also has improved hashes) -* Literal byte matching using SSE 4.2 for faster match comparisons. (not in Go) -* Bulk hashing on matches. (In Go 1.7) -* Much faster dictionary indexing with `NewWriterDict()`/`Reset()`. (In Go 1.7) -* Make Bit Coder faster by assuming we are on a 64 bit CPU. (In Go 1.7) -* Level 1 compression replaced by converted "Snappy" algorithm. (In Go 1.7) -* Uncompressible content is detected and skipped faster. (Only in BestSpeed in Go) -* A lot of branching eliminated by having two encoders for levels 4-6 and 7-9. (not in Go) -* All heap memory allocations eliminated. (In Go 1.7) +It has been a while since we have been looking at the speed of this package compared to the standard library, so I thought I would re-do my tests and give some overall recommendations based on the current state. All benchmarks have been performed with Go 1.10 on my Desktop Intel(R) Core(TM) i7-2600 CPU @3.40GHz. Since I last ran the tests, I have gotten more RAM, which means tests with big files are no longer limited by my SSD. -``` -benchmark old ns/op new ns/op delta -BenchmarkEncodeDigitsSpeed1e4-4 554029 265175 -52.14% -BenchmarkEncodeDigitsSpeed1e5-4 3908558 2416595 -38.17% -BenchmarkEncodeDigitsSpeed1e6-4 37546692 24875330 -33.75% -BenchmarkEncodeDigitsDefault1e4-4 781510 486322 -37.77% -BenchmarkEncodeDigitsDefault1e5-4 15530248 6740175 -56.60% -BenchmarkEncodeDigitsDefault1e6-4 174915710 76498625 -56.27% -BenchmarkEncodeDigitsCompress1e4-4 769995 485652 -36.93% -BenchmarkEncodeDigitsCompress1e5-4 15450113 6929589 -55.15% -BenchmarkEncodeDigitsCompress1e6-4 175114660 73348495 -58.11% -BenchmarkEncodeTwainSpeed1e4-4 560122 275977 -50.73% -BenchmarkEncodeTwainSpeed1e5-4 3740978 2506095 -33.01% -BenchmarkEncodeTwainSpeed1e6-4 35542802 21904440 -38.37% -BenchmarkEncodeTwainDefault1e4-4 828534 549026 -33.74% -BenchmarkEncodeTwainDefault1e5-4 13667153 7528455 -44.92% -BenchmarkEncodeTwainDefault1e6-4 141191770 79952170 -43.37% -BenchmarkEncodeTwainCompress1e4-4 830050 545694 -34.26% -BenchmarkEncodeTwainCompress1e5-4 16620852 8460600 -49.10% -BenchmarkEncodeTwainCompress1e6-4 193326820 90808750 -53.03% +The raw results are in my [updated spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing). Due to cgo changes and upstream updates i could not get the cgo version of gzip to compile. Instead I included the [zstd](https://github.com/datadog/zstd) cgo implementation. If I get cgo gzip to work again, I might replace the results in the sheet. -benchmark old MB/s new MB/s speedup -BenchmarkEncodeDigitsSpeed1e4-4 18.05 37.71 2.09x -BenchmarkEncodeDigitsSpeed1e5-4 25.58 41.38 1.62x -BenchmarkEncodeDigitsSpeed1e6-4 26.63 40.20 1.51x -BenchmarkEncodeDigitsDefault1e4-4 12.80 20.56 1.61x -BenchmarkEncodeDigitsDefault1e5-4 6.44 14.84 2.30x -BenchmarkEncodeDigitsDefault1e6-4 5.72 13.07 2.28x -BenchmarkEncodeDigitsCompress1e4-4 12.99 20.59 1.59x -BenchmarkEncodeDigitsCompress1e5-4 6.47 14.43 2.23x -BenchmarkEncodeDigitsCompress1e6-4 5.71 13.63 2.39x -BenchmarkEncodeTwainSpeed1e4-4 17.85 36.23 2.03x -BenchmarkEncodeTwainSpeed1e5-4 26.73 39.90 1.49x -BenchmarkEncodeTwainSpeed1e6-4 28.14 45.65 1.62x -BenchmarkEncodeTwainDefault1e4-4 12.07 18.21 1.51x -BenchmarkEncodeTwainDefault1e5-4 7.32 13.28 1.81x -BenchmarkEncodeTwainDefault1e6-4 7.08 12.51 1.77x -BenchmarkEncodeTwainCompress1e4-4 12.05 18.33 1.52x -BenchmarkEncodeTwainCompress1e5-4 6.02 11.82 1.96x -BenchmarkEncodeTwainCompress1e6-4 5.17 11.01 2.13x -``` -* "Speed" is compression level 1 -* "Default" is compression level 6 -* "Compress" is compression level 9 -* Test files are [Digits](https://github.com/klauspost/compress/blob/master/testdata/e.txt) (no matches) and [Twain](https://github.com/klauspost/compress/blob/master/testdata/Mark.Twain-Tom.Sawyer.txt) (plain text) . +The columns to take note of are: *MB/s* - the throughput. *Reduction* - the data size reduction in percent of the original. *Rel Speed* relative speed compared to the standard libary at the same level. *Smaller* - how many percent smaller is the compressed output compared to stdlib. Negative means the output was bigger. *Loss* means the loss (or gain) in compression as a percentage difference of the input. -As can be seen it shows a very good speedup all across the line. +The `gzstd` (standard library gzip) and `gzkp` (this package gzip) only uses one CPU core. [`pgzip`](https://github.com/klauspost/pgzip), [`bgzf`](https://github.com/biogo/hts/bgzf) uses all 4 cores. [`zstd`](https://github.com/DataDog/zstd) uses one core, and is a beast (but not Go, yet). -`Twain` is a much more realistic benchmark, and will be closer to JSON/HTML performance. Here speed is equivalent or faster, up to 2 times. -**Without assembly**. This is what you can expect on systems that does not have amd64 and SSE 4: -``` -benchmark old ns/op new ns/op delta -BenchmarkEncodeDigitsSpeed1e4-4 554029 249558 -54.96% -BenchmarkEncodeDigitsSpeed1e5-4 3908558 2295216 -41.28% -BenchmarkEncodeDigitsSpeed1e6-4 37546692 22594905 -39.82% -BenchmarkEncodeDigitsDefault1e4-4 781510 579850 -25.80% -BenchmarkEncodeDigitsDefault1e5-4 15530248 10096561 -34.99% -BenchmarkEncodeDigitsDefault1e6-4 174915710 111470780 -36.27% -BenchmarkEncodeDigitsCompress1e4-4 769995 579708 -24.71% -BenchmarkEncodeDigitsCompress1e5-4 15450113 10266373 -33.55% -BenchmarkEncodeDigitsCompress1e6-4 175114660 110170120 -37.09% -BenchmarkEncodeTwainSpeed1e4-4 560122 260679 -53.46% -BenchmarkEncodeTwainSpeed1e5-4 3740978 2097372 -43.94% -BenchmarkEncodeTwainSpeed1e6-4 35542802 20353449 -42.74% -BenchmarkEncodeTwainDefault1e4-4 828534 646016 -22.03% -BenchmarkEncodeTwainDefault1e5-4 13667153 10056369 -26.42% -BenchmarkEncodeTwainDefault1e6-4 141191770 105268770 -25.44% -BenchmarkEncodeTwainCompress1e4-4 830050 642401 -22.61% -BenchmarkEncodeTwainCompress1e5-4 16620852 11157081 -32.87% -BenchmarkEncodeTwainCompress1e6-4 193326820 121780770 -37.01% +## Overall differences. -benchmark old MB/s new MB/s speedup -BenchmarkEncodeDigitsSpeed1e4-4 18.05 40.07 2.22x -BenchmarkEncodeDigitsSpeed1e5-4 25.58 43.57 1.70x -BenchmarkEncodeDigitsSpeed1e6-4 26.63 44.26 1.66x -BenchmarkEncodeDigitsDefault1e4-4 12.80 17.25 1.35x -BenchmarkEncodeDigitsDefault1e5-4 6.44 9.90 1.54x -BenchmarkEncodeDigitsDefault1e6-4 5.72 8.97 1.57x -BenchmarkEncodeDigitsCompress1e4-4 12.99 17.25 1.33x -BenchmarkEncodeDigitsCompress1e5-4 6.47 9.74 1.51x -BenchmarkEncodeDigitsCompress1e6-4 5.71 9.08 1.59x -BenchmarkEncodeTwainSpeed1e4-4 17.85 38.36 2.15x -BenchmarkEncodeTwainSpeed1e5-4 26.73 47.68 1.78x -BenchmarkEncodeTwainSpeed1e6-4 28.14 49.13 1.75x -BenchmarkEncodeTwainDefault1e4-4 12.07 15.48 1.28x -BenchmarkEncodeTwainDefault1e5-4 7.32 9.94 1.36x -BenchmarkEncodeTwainDefault1e6-4 7.08 9.50 1.34x -BenchmarkEncodeTwainCompress1e4-4 12.05 15.57 1.29x -BenchmarkEncodeTwainCompress1e5-4 6.02 8.96 1.49x -BenchmarkEncodeTwainCompress1e6-4 5.17 8.21 1.59x -``` -So even without the assembly optimizations there is a general speedup across the board. +There appears to be a roughly 5-10% speed advantage over the standard library when comparing at similar compression levels. -## level 1-3 "snappy" compression +The biggest difference you will see is the result of [re-balancing](https://blog.klauspost.com/rebalancing-deflate-compression-levels/) the compression levels. I wanted by library to give a smoother transition between the compression levels than the standard library. -Levels 1 "Best Speed", 2 and 3 are completely replaced by a converted version of the algorithm found in Snappy, modified to be fully -compatible with the deflate bitstream (and thus still compatible with all existing zlib/gzip libraries and tools). -This version is considerably faster than the "old" deflate at level 1. It does however come at a compression loss, usually in the order of 3-4% compared to the old level 1. However, the speed is usually 1.75 times that of the fastest deflate mode. +This package attempts to provide a more smooth transition, where "1" is taking a lot of shortcuts, "5" is the reasonable trade-off and "9" is the "give me the best compression", and the values in between gives something reasonable in between. The standard library has big differences in levels 1-4, but levels 5-9 having no significant gains - often spending a lot more time than can be justified by the achieved compression. -In my previous experiments the most common case for "level 1" was that it provided no significant speedup, only lower compression compared to level 2 and sometimes even 3. However, the modified Snappy algorithm provides a very good sweet spot. Usually about 75% faster and with only little compression loss. Therefore I decided to *replace* level 1 with this mode entirely. +There are links to all the test data in the [spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing) in the top left field on each tab. -Input is split into blocks of 64kb of, and they are encoded independently (no backreferences across blocks) for the best speed. Contrary to Snappy the output is entropy-encoded, so you will almost always see better compression than Snappy. But Snappy is still about twice as fast as Snappy in deflate mode. +## Web Content -Level 2 and 3 have also been replaced. Level 2 is capable is matching between blocks and level 3 checks up to two hashes for matches it will try. +This test set aims to emulate typical use in a web server. The test-set is 4GB data in 53k files, and is a mixture of (mostly) HTML, JS, CSS. -## compression levels +Since level 1 and 9 are close to being the same code, they are quite close. But looking at the levels in-between the differences are quite big. -This table shows the compression at each level, and the percentage of the output size compared to output -at the similar level with the standard library. Compression data is `Twain`, see above. +Looking at level 6, this package is 88% faster, but will output about 6% more data. For a web server, this means you can serve 88% more data, but have to pay for 6% more bandwidth. You can draw your own conclusions on what would be the most expensive for your case. -(Not up-to-date after rebalancing) +## Object files -| Level | Bytes | % size | -|-------|--------|--------| -| 1 | 194622 | 103.7% | -| 2 | 174684 | 96.85% | -| 3 | 170301 | 98.45% | -| 4 | 165253 | 97.69% | -| 5 | 161274 | 98.65% | -| 6 | 160464 | 99.71% | -| 7 | 160304 | 99.87% | -| 8 | 160279 | 99.99% | -| 9 | 160279 | 99.99% | +This test is for typical data files stored on a server. In this case it is a collection of Go precompiled objects. They are very compressible. -To interpret and example, this version of deflate compresses input of 407287 bytes to 161274 bytes at level 5, which is 98.6% of the size of what the standard library produces; 161274 bytes. +The picture is similar to the web content, but with small differences since this is very compressible. Levels 2-3 offer good speed, but is sacrificing quite a bit of compression. + +The standard library seems suboptimal on level 3 and 4 - offering both worse compression and speed than level 6 & 7 of this package respectively. + +## Highly Compressible File + +This is a JSON file with very high redundancy. The reduction starts at 95% on level 1, so in real life terms we are dealing with something like a highly redundant stream of data, etc. + +It is definitely visible that we are dealing with specialized content here, so the results are very scattered. This package does not do very well at levels 1-4, but picks up significantly at level 5 and levels 7 and 8 offering great speed for the achieved compression. + +So if you know you content is extremely compressible you might want to go slightly higher than the defaults. The standard library has a huge gap between levels 3 and 4 in terms of speed (2.75x slowdown), so it offers little "middle ground". + +## Medium-High Compressible + +This is a pretty common test corpus: [enwik9](http://mattmahoney.net/dc/textdata.html). It contains the first 10^9 bytes of the English Wikipedia dump on Mar. 3, 2006. This is a very good test of typical text based compression and more data heavy streams. + +We see a similar picture here as in "Web Content". On equal levels some compression is sacrificed for more speed. Level 5 seems to be the best trade-off between speed and size, beating stdlib level 3 in both. + +## Medium Compressible + +I will combine two test sets, one [10GB file set](http://mattmahoney.net/dc/10gb.html) and a VM disk image (~8GB). Both contain different data types and represent a typical backup scenario. + +The most notable thing is how quickly the standard libary drops to very low compression speeds around level 5-6 without any big gains in compression. Since this type of data is fairly common, this does not seem like good behavior. + + +## Un-compressible Content + +This is mainly a test of how good the algorithms are at detecting un-compressible input. The standard library only offers this feature with very conservative settings at level 1. Obviously there is no reason for the algorithms to try to compress input that cannot be compressed. The only downside is that it might skip some compressible data on false detections. -This means that from level 4 you can expect a compression level increase of a few percent. Level 1 is about 3% worse, as descibed above. # linear time compression (huffman only) -This compression library adds a special compression level, named `ConstantCompression`, which allows near linear time compression. This is done by completely disabling matching of previous data, and only reduce the number of bits to represent each character. +This compression library adds a special compression level, named `HuffmanOnly`, which allows near linear time compression. This is done by completely disabling matching of previous data, and only reduce the number of bits to represent each character. This means that often used characters, like 'e' and ' ' (space) in text use the fewest bits to represent, and rare characters like '¤' takes more bits to represent. For more information see [wikipedia](https://en.wikipedia.org/wiki/Huffman_coding) or this nice [video](https://youtu.be/ZdooBTdW5bM). @@ -217,66 +147,6 @@ For more information see my blog post on [Fast Linear Time Compression](http://b This is implemented on Go 1.7 as "Huffman Only" mode, though not exposed for gzip. -# gzip/zip optimizations - * Uses the faster deflate - * Uses SSE 4.2 CRC32 calculations. - -Speed increase is up to 3x of the standard library, but usually around 2x. - -This is close to a real world benchmark as you will get. A 2.3MB JSON file. (NOTE: not up-to-date) - -``` -benchmark old ns/op new ns/op delta -BenchmarkGzipL1-4 95212470 59938275 -37.05% -BenchmarkGzipL2-4 102069730 76349195 -25.20% -BenchmarkGzipL3-4 115472770 82492215 -28.56% -BenchmarkGzipL4-4 153197780 107570890 -29.78% -BenchmarkGzipL5-4 203930260 134387930 -34.10% -BenchmarkGzipL6-4 233172100 145495400 -37.60% -BenchmarkGzipL7-4 297190260 197926950 -33.40% -BenchmarkGzipL8-4 512819750 376244733 -26.63% -BenchmarkGzipL9-4 563366800 403266833 -28.42% - -benchmark old MB/s new MB/s speedup -BenchmarkGzipL1-4 52.11 82.78 1.59x -BenchmarkGzipL2-4 48.61 64.99 1.34x -BenchmarkGzipL3-4 42.97 60.15 1.40x -BenchmarkGzipL4-4 32.39 46.13 1.42x -BenchmarkGzipL5-4 24.33 36.92 1.52x -BenchmarkGzipL6-4 21.28 34.10 1.60x -BenchmarkGzipL7-4 16.70 25.07 1.50x -BenchmarkGzipL8-4 9.68 13.19 1.36x -BenchmarkGzipL9-4 8.81 12.30 1.40x -``` - -Multithreaded compression using [pgzip](https://github.com/klauspost/pgzip) comparison, Quadcore, CPU = 8: - -(Not updated, old numbers) - -``` -benchmark old ns/op new ns/op delta -BenchmarkGzipL1 96155500 25981486 -72.98% -BenchmarkGzipL2 101905830 24601408 -75.86% -BenchmarkGzipL3 113506490 26321506 -76.81% -BenchmarkGzipL4 143708220 31761818 -77.90% -BenchmarkGzipL5 188210770 39602266 -78.96% -BenchmarkGzipL6 209812000 40402313 -80.74% -BenchmarkGzipL7 270015440 56103210 -79.22% -BenchmarkGzipL8 461359700 91255220 -80.22% -BenchmarkGzipL9 498361833 88755075 -82.19% - -benchmark old MB/s new MB/s speedup -BenchmarkGzipL1 51.60 190.97 3.70x -BenchmarkGzipL2 48.69 201.69 4.14x -BenchmarkGzipL3 43.71 188.51 4.31x -BenchmarkGzipL4 34.53 156.22 4.52x -BenchmarkGzipL5 26.36 125.29 4.75x -BenchmarkGzipL6 23.65 122.81 5.19x -BenchmarkGzipL7 18.38 88.44 4.81x -BenchmarkGzipL8 10.75 54.37 5.06x -BenchmarkGzipL9 9.96 55.90 5.61x -``` - # snappy package The standard snappy package has now been improved. This repo contains a copy of the snappy repo. diff --git a/vendor/github.com/klauspost/compress/compressible.go b/vendor/github.com/klauspost/compress/compressible.go new file mode 100644 index 0000000..59bf962 --- /dev/null +++ b/vendor/github.com/klauspost/compress/compressible.go @@ -0,0 +1,63 @@ +package compress + +import "math" + +// Estimate returns a normalized compressibility estimate of block b. +// Values close to zero are likely uncompressible. +// Values above 0.1 are likely to be compressible. +// Values above 0.5 are very compressible. +// Very small lengths will return 0. +func Estimate(b []byte) float64 { + if len(b) < 16 { + return 0 + } + + // Correctly predicted order 1 + hits := 0 + lastMatch := false + var o1 [256]byte + var hist [256]int + c1 := byte(0) + for _, c := range b { + if c == o1[c1] { + // We only count a hit if there was two correct predictions in a row. + if lastMatch { + hits++ + } + lastMatch = true + } else { + lastMatch = false + } + o1[c1] = c + c1 = c + hist[c]++ + } + + // Use x^0.6 to give better spread + prediction := math.Pow(float64(hits)/float64(len(b)), 0.6) + + // Calculate histogram distribution + variance := float64(0) + avg := float64(len(b)) / 256 + + for _, v := range hist { + Δ := float64(v) - avg + variance += Δ * Δ + } + + stddev := math.Sqrt(float64(variance)) / float64(len(b)) + exp := math.Sqrt(1 / float64(len(b))) + + // Subtract expected stddev + stddev -= exp + if stddev < 0 { + stddev = 0 + } + stddev *= 1 + exp + + // Use x^0.4 to give better spread + entropy := math.Pow(stddev, 0.4) + + // 50/50 weight between prediction and histogram distribution + return math.Pow((prediction+entropy)/2, 0.9) +} diff --git a/vendor/github.com/klauspost/compress/compressible_test.go b/vendor/github.com/klauspost/compress/compressible_test.go new file mode 100644 index 0000000..af508df --- /dev/null +++ b/vendor/github.com/klauspost/compress/compressible_test.go @@ -0,0 +1,121 @@ +package compress + +import ( + "crypto/rand" + "encoding/base32" + "testing" +) + +func BenchmarkEstimate(b *testing.B) { + b.ReportAllocs() + // (predictable, low entropy distibution) + b.Run("zeroes-5k", func(b *testing.B) { + var testData = make([]byte, 5000) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (predictable, high entropy distibution) + b.Run("predictable-5k", func(b *testing.B) { + var testData = make([]byte, 5000) + for i := range testData { + testData[i] = byte(float64(i) / float64(len(testData)) * 256) + } + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (not predictable, high entropy distibution) + b.Run("random-500b", func(b *testing.B) { + var testData = make([]byte, 500) + rand.Read(testData) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (not predictable, high entropy distibution) + b.Run("random-5k", func(b *testing.B) { + var testData = make([]byte, 5000) + rand.Read(testData) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (not predictable, high entropy distibution) + b.Run("random-50k", func(b *testing.B) { + var testData = make([]byte, 50000) + rand.Read(testData) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (not predictable, high entropy distibution) + b.Run("random-500k", func(b *testing.B) { + var testData = make([]byte, 500000) + rand.Read(testData) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + + // (not predictable, medium entropy distibution) + b.Run("base-32-5k", func(b *testing.B) { + var testData = make([]byte, 5000) + rand.Read(testData) + s := base32.StdEncoding.EncodeToString(testData) + testData = []byte(s) + testData = testData[:5000] + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) + // (medium predictable, medium entropy distibution) + b.Run("text", func(b *testing.B) { + var testData = []byte(`If compression is done per-chunk, care should be taken that it doesn't leave restic backups open to watermarking/fingerprinting attacks. +This is essentially the same problem we discussed related to fingerprinting the CDC deduplication process: +With "naive" CDC, a "known plaintext" file can be verified to exist within the backup if the size of individual blocks can be observed by an attacker, by using CDC on the file in parallel and comparing the resulting amount of chunks and individual chunk lengths. +As discussed earlier, this can be somewhat mitigated by salting the CDC algorithm with a secret value, as done in attic. +With salted CDC, I assume compression would happen on each individual chunk, after splitting the problematic file into chunks. Restic chunks are in the range of 512 KB to 8 MB (but not evenly distributed - right?). +Attacker knows that the CDC algorithm uses a secret salt, so the attacker generates a range of chunks consisting of the first 512 KB to 8 MB of the file, one for each valid chunk length. The attacker is also able to determine the lengths of compressed chunks. +The attacker then compresses that chunk using the compression algorithm. +The attacker compares the lengths of the resulting chunks to the first chunk in the restic backup sets. +IF a matching block length is found, the attacker repeats the exercise with the next chunk, and the next chunk, and the next chunk, ... and the next chunk. +It is my belief that with sufficiently large files, and considering the fact that the CDC algorithm is "biased" (in lack of better of words) towards generating blocks of about 1 MB, this would be sufficient to ascertain whether or not a certain large file exists in the backup. +AS always, a paranoid and highly unscientific stream of consciousness. +Thoughts?`) + testData = append(testData, testData...) + testData = append(testData, testData...) + b.SetBytes(int64(len(testData))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Estimate(testData) + } + b.Log(Estimate(testData)) + }) +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go index 53b63d9..800d0ce 100644 --- a/vendor/github.com/klauspost/compress/flate/inflate.go +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -10,12 +10,14 @@ package flate import ( "bufio" "io" + "math/bits" "strconv" "sync" ) const ( - maxCodeLen = 16 // max length of Huffman code + maxCodeLen = 16 // max length of Huffman code + maxCodeLenMask = 15 // mask for max length of Huffman code // The next three numbers come from the RFC section 3.2.7, with the // additional proviso in section 3.2.5 which implies that distance codes // 30 and 31 should never occur in compressed data. @@ -101,10 +103,10 @@ const ( ) type huffmanDecoder struct { - min int // the minimum code length - chunks [huffmanNumChunks]uint32 // chunks as described above - links [][]uint32 // overflow links - linkMask uint32 // mask the width of the link table + min int // the minimum code length + chunks *[huffmanNumChunks]uint32 // chunks as described above + links [][]uint32 // overflow links + linkMask uint32 // mask the width of the link table } // Initialize Huffman decoding tables from array of code lengths. @@ -112,21 +114,24 @@ type huffmanDecoder struct { // tree (i.e., neither over-subscribed nor under-subscribed). The exception is a // degenerate case where the tree has only a single symbol with length 1. Empty // trees are permitted. -func (h *huffmanDecoder) init(bits []int) bool { +func (h *huffmanDecoder) init(lengths []int) bool { // Sanity enables additional runtime tests during Huffman // table construction. It's intended to be used during // development to supplement the currently ad-hoc unit tests. const sanity = false + if h.chunks == nil { + h.chunks = &[huffmanNumChunks]uint32{} + } if h.min != 0 { - *h = huffmanDecoder{} + *h = huffmanDecoder{chunks: h.chunks, links: h.links} } // Count number of codes of each length, // compute min and max length. var count [maxCodeLen]int var min, max int - for _, n := range bits { + for _, n := range lengths { if n == 0 { continue } @@ -136,7 +141,7 @@ func (h *huffmanDecoder) init(bits []int) bool { if n > max { max = n } - count[n]++ + count[n&maxCodeLenMask]++ } // Empty tree. The decompressor.huffSym function will fail later if the tree @@ -154,8 +159,8 @@ func (h *huffmanDecoder) init(bits []int) bool { var nextcode [maxCodeLen]int for i := min; i <= max; i++ { code <<= 1 - nextcode[i] = code - code += count[i] + nextcode[i&maxCodeLenMask] = code + code += count[i&maxCodeLenMask] } // Check that the coding is complete (i.e., that we've @@ -168,33 +173,49 @@ func (h *huffmanDecoder) init(bits []int) bool { } h.min = min + chunks := h.chunks[:] + for i := range chunks { + chunks[i] = 0 + } + if max > huffmanChunkBits { numLinks := 1 << (uint(max) - huffmanChunkBits) h.linkMask = uint32(numLinks - 1) // create link tables link := nextcode[huffmanChunkBits+1] >> 1 - h.links = make([][]uint32, huffmanNumChunks-link) + if cap(h.links) < huffmanNumChunks-link { + h.links = make([][]uint32, huffmanNumChunks-link) + } else { + h.links = h.links[:huffmanNumChunks-link] + } for j := uint(link); j < huffmanNumChunks; j++ { - reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8 + reverse := int(bits.Reverse16(uint16(j))) reverse >>= uint(16 - huffmanChunkBits) off := j - uint(link) if sanity && h.chunks[reverse] != 0 { panic("impossible: overwriting existing chunk") } h.chunks[reverse] = uint32(off<>8]) | int(reverseByte[code&0xff])<<8 + reverse := int(bits.Reverse16(uint16(code))) reverse >>= uint(16 - n) if n <= huffmanChunkBits { for off := reverse; off < len(h.chunks); off += 1 << uint(n) { @@ -589,7 +610,7 @@ readLiteral: return } } - dist = int(reverseByte[(f.b&0x1F)<<3]) + dist = int(bits.Reverse8(uint8(f.b & 0x1F << 3))) f.b >>= 5 f.nb -= 5 } else { @@ -661,10 +682,7 @@ func (f *decompressor) dataBlock() { nr, err := io.ReadFull(f.r, f.buf[0:4]) f.roffset += int64(nr) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } n := int(f.buf[0]) | int(f.buf[1])<<8 @@ -697,10 +715,7 @@ func (f *decompressor) copyData() { f.copyLen -= cnt f.dict.writeMark(cnt) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } @@ -722,13 +737,18 @@ func (f *decompressor) finishBlock() { f.step = (*decompressor).nextBlock } +// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF. +func noEOF(e error) error { + if e == io.EOF { + return io.ErrUnexpectedEOF + } + return e +} + func (f *decompressor) moreBits() error { c, err := f.r.ReadByte() if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return err + return noEOF(err) } f.roffset++ f.b |= uint32(c) << f.nb @@ -743,25 +763,37 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { // cases, the chunks slice will be 0 for the invalid sequence, leading it // satisfy the n == 0 check below. n := uint(h.min) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b for { - for f.nb < n { - if err := f.moreBits(); err != nil { - return 0, err + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + return 0, noEOF(err) } + f.roffset++ + b |= uint32(c) << (nb & 31) + nb += 8 } - chunk := h.chunks[f.b&(huffmanNumChunks-1)] + chunk := h.chunks[b&(huffmanNumChunks-1)] n = uint(chunk & huffmanCountMask) if n > huffmanChunkBits { - chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask] + chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask] n = uint(chunk & huffmanCountMask) } - if n <= f.nb { + if n <= nb { if n == 0 { + f.b = b + f.nb = nb f.err = CorruptInputError(f.roffset) return 0, f.err } - f.b >>= n - f.nb -= n + f.b = b >> (n & 31) + f.nb = nb - n return int(chunk >> huffmanValueShift), nil } } @@ -799,6 +831,8 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error { r: makeReader(r), bits: f.bits, codebits: f.codebits, + h1: f.h1, + h2: f.h2, dict: f.dict, step: (*decompressor).nextBlock, } diff --git a/vendor/github.com/klauspost/compress/flate/reader_test.go b/vendor/github.com/klauspost/compress/flate/reader_test.go index e42bd01..5543964 100644 --- a/vendor/github.com/klauspost/compress/flate/reader_test.go +++ b/vendor/github.com/klauspost/compress/flate/reader_test.go @@ -25,6 +25,7 @@ func TestNlitOutOfRange(t *testing.T) { const ( digits = iota twain + random ) var testfiles = []string{ @@ -34,6 +35,8 @@ var testfiles = []string{ digits: "../testdata/e.txt", // Twain is Project Gutenberg's edition of Mark Twain's classic English novel. twain: "../testdata/Mark.Twain-Tom.Sawyer.txt", + // Random bytes + random: "../testdata/sharnd.out", } func benchmarkDecode(b *testing.B, testfile, level, n int) { @@ -63,8 +66,11 @@ func benchmarkDecode(b *testing.B, testfile, level, n int) { buf0, compressed, w = nil, nil, nil runtime.GC() b.StartTimer() + r := NewReader(bytes.NewReader(buf1)) + res := r.(Resetter) for i := 0; i < b.N; i++ { - io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1))) + res.Reset(bytes.NewReader(buf1), nil) + io.Copy(ioutil.Discard, r) } } @@ -95,3 +101,6 @@ func BenchmarkDecodeTwainDefault1e6(b *testing.B) { benchmarkDecode(b, twain, func BenchmarkDecodeTwainCompress1e4(b *testing.B) { benchmarkDecode(b, twain, compress, 1e4) } func BenchmarkDecodeTwainCompress1e5(b *testing.B) { benchmarkDecode(b, twain, compress, 1e5) } func BenchmarkDecodeTwainCompress1e6(b *testing.B) { benchmarkDecode(b, twain, compress, 1e6) } +func BenchmarkDecodeRandomSpeed1e4(b *testing.B) { benchmarkDecode(b, random, speed, 1e4) } +func BenchmarkDecodeRandomSpeed1e5(b *testing.B) { benchmarkDecode(b, random, speed, 1e5) } +func BenchmarkDecodeRandomSpeed1e6(b *testing.B) { benchmarkDecode(b, random, speed, 1e6) } diff --git a/vendor/github.com/klauspost/compress/fse/README.md b/vendor/github.com/klauspost/compress/fse/README.md new file mode 100644 index 0000000..ea7324d --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/README.md @@ -0,0 +1,79 @@ +# Finite State Entropy + +This package provides Finite State Entropy encoding and decoding. + +Finite State Entropy (also referenced as [tANS](https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#tANS)) +encoding provides a fast near-optimal symbol encoding/decoding +for byte blocks as implemented in [zstandard](https://github.com/facebook/zstd). + +This can be used for compressing input with a lot of similar input values to the smallest number of bytes. +This does not perform any multi-byte [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) as LZ coders, +but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding. + +* [Godoc documentation](https://godoc.org/github.com/klauspost/compress/fse) + +## News + + * Feb 2018: First implementation released. Consider this beta software for now. + +# Usage + +This package provides a low level interface that allows to compress single independent blocks. + +Each block is separate, and there is no built in integrity checks. +This means that the caller should keep track of block sizes and also do checksums if needed. + +Compressing a block is done via the [`Compress`](https://godoc.org/github.com/klauspost/compress/fse#Compress) function. +You must provide input and will receive the output and maybe an error. + +These error values can be returned: + +| Error | Description | +|---------------------|-----------------------------------------------------------------------------| +| `` | Everything ok, output is returned | +| `ErrIncompressible` | Returned when input is judged to be too hard to compress | +| `ErrUseRLE` | Returned from the compressor when the input is a single byte value repeated | +| `(error)` | An internal error occurred. | + +As can be seen above there are errors that will be returned even under normal operation so it is important to handle these. + +To reduce allocations you can provide a [`Scratch`](https://godoc.org/github.com/klauspost/compress/fse#Scratch) object +that can be re-used for successive calls. Both compression and decompression accepts a `Scratch` object, and the same +object can be used for both. + +Be aware, that when re-using a `Scratch` object that the *output* buffer is also re-used, so if you are still using this +you must set the `Out` field in the scratch to nil. The same buffer is used for compression and decompression output. + +Decompressing is done by calling the [`Decompress`](https://godoc.org/github.com/klauspost/compress/fse#Decompress) function. +You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back +your input was likely corrupted. + +It is important to note that a successful decoding does *not* mean your output matches your original input. +There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid. + +For more detailed usage, see examples in the [godoc documentation](https://godoc.org/github.com/klauspost/compress/fse#pkg-examples). + +# Performance + +A lot of factors are affecting speed. Block sizes and compressibility of the material are primary factors. +All compression functions are currently only running on the calling goroutine so only one core will be used per block. + +The compressor is significantly faster if symbols are kept as small as possible. The highest byte value of the input +is used to reduce some of the processing, so if all your input is above byte value 64 for instance, it may be +beneficial to transpose all your input values down by 64. + +With moderate block sizes around 64k speed are typically 200MB/s per core for compression and +around 300MB/s decompression speed. + +The same hardware typically does Huffman (deflate) encoding at 125MB/s and decompression at 100MB/s. + +# Plans + +At one point, more internals will be exposed to facilitate more "expert" usage of the components. + +A streaming interface is also likely to be implemented. Likely compatible with [FSE stream format](https://github.com/Cyan4973/FiniteStateEntropy/blob/dev/programs/fileio.c#L261). + +# Contributing + +Contributions are always welcome. Be aware that adding public functions will require good justification and breaking +changes will likely not be accepted. If in doubt open an issue before writing the PR. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/bitreader.go b/vendor/github.com/klauspost/compress/fse/bitreader.go new file mode 100644 index 0000000..b9db204 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bitreader.go @@ -0,0 +1,107 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import ( + "errors" + "io" +) + +// bitReader reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReader struct { + in []byte + off uint // next byte to read is at in[off - 1] + value uint64 + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReader) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + b.off = uint(len(in)) + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + b.fill() + b.fill() + b.bitsRead += 8 - uint8(highBits(uint32(v))) + return nil +} + +// getBits will return n bits. n can be 0. +func (b *bitReader) getBits(n uint8) uint16 { + if n == 0 || b.bitsRead >= 64 { + return 0 + } + return b.getBitsFast(n) +} + +// getBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReader) getBitsFast(n uint8) uint16 { + const regMask = 64 - 1 + v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) + b.bitsRead += n + return v +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReader) fillFast() { + if b.bitsRead < 32 { + return + } + // Do single re-slice to avoid bounds checks. + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReader) fill() { + if b.bitsRead < 32 { + return + } + if b.off > 4 { + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 + return + } + for b.off > 0 { + b.value = (b.value << 8) | uint64(b.in[b.off-1]) + b.bitsRead -= 8 + b.off-- + } +} + +// finished returns true if all bits have been read from the bit stream. +func (b *bitReader) finished() bool { + return b.off == 0 && b.bitsRead >= 64 +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReader) close() error { + // Release reference. + b.in = nil + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/fse/bitwriter.go b/vendor/github.com/klauspost/compress/fse/bitwriter.go new file mode 100644 index 0000000..43e4636 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bitwriter.go @@ -0,0 +1,168 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import "fmt" + +// bitWriter will write bits. +// First bit will be LSB of the first byte of output. +type bitWriter struct { + bitContainer uint64 + nBits uint8 + out []byte +} + +// bitMask16 is bitmasks. Has extra to avoid bounds check. +var bitMask16 = [32]uint16{ + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF} /* up to 16 bits */ + +// addBits16NC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16NC(value uint16, bits uint8) { + b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16ZeroNC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +// This is fastest if bits can be zero. +func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) { + if bits == 0 { + return + } + value <<= (16 - bits) & 15 + value >>= (16 - bits) & 15 + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// flush will flush all pending full bytes. +// There will be at least 56 bits available for writing when this has been called. +// Using flush32 is faster, but leaves less space for writing. +func (b *bitWriter) flush() { + v := b.nBits >> 3 + switch v { + case 0: + case 1: + b.out = append(b.out, + byte(b.bitContainer), + ) + case 2: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + ) + case 3: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + ) + case 4: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + ) + case 5: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + ) + case 6: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + ) + case 7: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + ) + case 8: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + byte(b.bitContainer>>56), + ) + default: + panic(fmt.Errorf("bits (%d) > 64", b.nBits)) + } + b.bitContainer >>= v << 3 + b.nBits &= 7 +} + +// flush32 will flush out, so there are at least 32 bits available for writing. +func (b *bitWriter) flush32() { + if b.nBits < 32 { + return + } + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24)) + b.nBits -= 32 + b.bitContainer >>= 32 +} + +// flushAlign will flush remaining full bytes and align to next byte boundary. +func (b *bitWriter) flushAlign() { + nbBytes := (b.nBits + 7) >> 3 + for i := uint8(0); i < nbBytes; i++ { + b.out = append(b.out, byte(b.bitContainer>>(i*8))) + } + b.nBits = 0 + b.bitContainer = 0 +} + +// close will write the alignment bit and write the final byte(s) +// to the output. +func (b *bitWriter) close() error { + // End mark + b.addBits16Clean(1, 1) + // flush until next byte. + b.flushAlign() + return nil +} + +// reset and continue writing by appending to out. +func (b *bitWriter) reset(out []byte) { + b.bitContainer = 0 + b.nBits = 0 + b.out = out +} diff --git a/vendor/github.com/klauspost/compress/fse/bytereader.go b/vendor/github.com/klauspost/compress/fse/bytereader.go new file mode 100644 index 0000000..f228a46 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bytereader.go @@ -0,0 +1,56 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +// byteReader provides a byte reader that reads +// little endian values from a byte stream. +// The input stream is manually advanced. +// The reader performs no bounds checks. +type byteReader struct { + b []byte + off int +} + +// init will initialize the reader and set the input. +func (b *byteReader) init(in []byte) { + b.b = in + b.off = 0 +} + +// advance the stream b n bytes. +func (b *byteReader) advance(n uint) { + b.off += int(n) +} + +// Int32 returns a little endian int32 starting at current offset. +func (b byteReader) Int32() int32 { + b2 := b.b[b.off : b.off+4 : b.off+4] + v3 := int32(b2[3]) + v2 := int32(b2[2]) + v1 := int32(b2[1]) + v0 := int32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// Uint32 returns a little endian uint32 starting at current offset. +func (b byteReader) Uint32() uint32 { + b2 := b.b[b.off : b.off+4 : b.off+4] + v3 := uint32(b2[3]) + v2 := uint32(b2[2]) + v1 := uint32(b2[1]) + v0 := uint32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// unread returns the unread portion of the input. +func (b byteReader) unread() []byte { + return b.b[b.off:] +} + +// remain will return the number of bytes remaining. +func (b byteReader) remain() int { + return len(b.b) - b.off +} diff --git a/vendor/github.com/klauspost/compress/fse/compress.go b/vendor/github.com/klauspost/compress/fse/compress.go new file mode 100644 index 0000000..398e974 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/compress.go @@ -0,0 +1,684 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import ( + "errors" + "fmt" +) + +// Compress the input bytes. Input must be < 2GB. +// Provide a Scratch buffer to avoid memory allocations. +// Note that the output is also kept in the scratch buffer. +// If input is too hard to compress, ErrIncompressible is returned. +// If input is a single byte value repeated ErrUseRLE is returned. +func Compress(in []byte, s *Scratch) ([]byte, error) { + if len(in) <= 1 { + return nil, ErrIncompressible + } + if len(in) >= 2<<30 { + return nil, errors.New("input too big, must be < 2GB") + } + s, err := s.prepare(in) + if err != nil { + return nil, err + } + + // Create histogram, if none was provided. + maxCount := s.maxCount + if maxCount == 0 { + maxCount = s.countSimple(in) + } + // Reset for next run. + s.clearCount = true + s.maxCount = 0 + if maxCount == len(in) { + // One symbol, use RLE + return nil, ErrUseRLE + } + if maxCount == 1 || maxCount < (len(in)>>7) { + // Each symbol present maximum once or too well distributed. + return nil, ErrIncompressible + } + s.optimalTableLog() + err = s.normalizeCount() + if err != nil { + return nil, err + } + err = s.writeCount() + if err != nil { + return nil, err + } + + if false { + err = s.validateNorm() + if err != nil { + return nil, err + } + } + + err = s.buildCTable() + if err != nil { + return nil, err + } + err = s.compress(in) + if err != nil { + return nil, err + } + s.Out = s.bw.out + // Check if we compressed. + if len(s.Out) >= len(in) { + return nil, ErrIncompressible + } + return s.Out, nil +} + +// cState contains the compression state of a stream. +type cState struct { + bw *bitWriter + stateTable []uint16 + state uint16 +} + +// init will initialize the compression state to the first symbol of the stream. +func (c *cState) init(bw *bitWriter, ct *cTable, tableLog uint8, first symbolTransform) { + c.bw = bw + c.stateTable = ct.stateTable + + nbBitsOut := (first.deltaNbBits + (1 << 15)) >> 16 + im := int32((nbBitsOut << 16) - first.deltaNbBits) + lu := (im >> nbBitsOut) + first.deltaFindState + c.state = c.stateTable[lu] + return +} + +// encode the output symbol provided and write it to the bitstream. +func (c *cState) encode(symbolTT symbolTransform) { + nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16 + dstState := int32(c.state>>(nbBitsOut&15)) + symbolTT.deltaFindState + c.bw.addBits16NC(c.state, uint8(nbBitsOut)) + c.state = c.stateTable[dstState] +} + +// encode the output symbol provided and write it to the bitstream. +func (c *cState) encodeZero(symbolTT symbolTransform) { + nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16 + dstState := int32(c.state>>(nbBitsOut&15)) + symbolTT.deltaFindState + c.bw.addBits16ZeroNC(c.state, uint8(nbBitsOut)) + c.state = c.stateTable[dstState] +} + +// flush will write the tablelog to the output and flush the remaining full bytes. +func (c *cState) flush(tableLog uint8) { + c.bw.flush32() + c.bw.addBits16NC(c.state, tableLog) + c.bw.flush() +} + +// compress is the main compression loop that will encode the input from the last byte to the first. +func (s *Scratch) compress(src []byte) error { + if len(src) <= 2 { + return errors.New("compress: src too small") + } + tt := s.ct.symbolTT[:256] + s.bw.reset(s.Out) + + // Our two states each encodes every second byte. + // Last byte encoded (first byte decoded) will always be encoded by c1. + var c1, c2 cState + + // Encode so remaining size is divisible by 4. + ip := len(src) + if ip&1 == 1 { + c1.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-1]]) + c2.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-2]]) + c1.encodeZero(tt[src[ip-3]]) + ip -= 3 + } else { + c2.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-1]]) + c1.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-2]]) + ip -= 2 + } + if ip&2 != 0 { + c2.encodeZero(tt[src[ip-1]]) + c1.encodeZero(tt[src[ip-2]]) + ip -= 2 + } + + // Main compression loop. + switch { + case !s.zeroBits && s.actualTableLog <= 8: + // We can encode 4 symbols without requiring a flush. + // We do not need to check if any output is 0 bits. + for ip >= 4 { + s.bw.flush32() + v3, v2, v1, v0 := src[ip-4], src[ip-3], src[ip-2], src[ip-1] + c2.encode(tt[v0]) + c1.encode(tt[v1]) + c2.encode(tt[v2]) + c1.encode(tt[v3]) + ip -= 4 + } + case !s.zeroBits: + // We do not need to check if any output is 0 bits. + for ip >= 4 { + s.bw.flush32() + v3, v2, v1, v0 := src[ip-4], src[ip-3], src[ip-2], src[ip-1] + c2.encode(tt[v0]) + c1.encode(tt[v1]) + s.bw.flush32() + c2.encode(tt[v2]) + c1.encode(tt[v3]) + ip -= 4 + } + case s.actualTableLog <= 8: + // We can encode 4 symbols without requiring a flush + for ip >= 4 { + s.bw.flush32() + v3, v2, v1, v0 := src[ip-4], src[ip-3], src[ip-2], src[ip-1] + c2.encodeZero(tt[v0]) + c1.encodeZero(tt[v1]) + c2.encodeZero(tt[v2]) + c1.encodeZero(tt[v3]) + ip -= 4 + } + default: + for ip >= 4 { + s.bw.flush32() + v3, v2, v1, v0 := src[ip-4], src[ip-3], src[ip-2], src[ip-1] + c2.encodeZero(tt[v0]) + c1.encodeZero(tt[v1]) + s.bw.flush32() + c2.encodeZero(tt[v2]) + c1.encodeZero(tt[v3]) + ip -= 4 + } + } + + // Flush final state. + // Used to initialize state when decoding. + c2.flush(s.actualTableLog) + c1.flush(s.actualTableLog) + + return s.bw.close() +} + +// writeCount will write the normalized histogram count to header. +// This is read back by readNCount. +func (s *Scratch) writeCount() error { + var ( + tableLog = s.actualTableLog + tableSize = 1 << tableLog + previous0 bool + charnum uint16 + + maxHeaderSize = ((int(s.symbolLen) * int(tableLog)) >> 3) + 3 + + // Write Table Size + bitStream = uint32(tableLog - minTablelog) + bitCount = uint(4) + remaining = int16(tableSize + 1) /* +1 for extra accuracy */ + threshold = int16(tableSize) + nbBits = uint(tableLog + 1) + ) + if cap(s.Out) < maxHeaderSize { + s.Out = make([]byte, 0, s.br.remain()+maxHeaderSize) + } + outP := uint(0) + out := s.Out[:maxHeaderSize] + + // stops at 1 + for remaining > 1 { + if previous0 { + start := charnum + for s.norm[charnum] == 0 { + charnum++ + } + for charnum >= start+24 { + start += 24 + bitStream += uint32(0xFFFF) << bitCount + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + } + for charnum >= start+3 { + start += 3 + bitStream += 3 << bitCount + bitCount += 2 + } + bitStream += uint32(charnum-start) << bitCount + bitCount += 2 + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + count := s.norm[charnum] + charnum++ + max := (2*threshold - 1) - remaining + if count < 0 { + remaining += count + } else { + remaining -= count + } + count++ // +1 for extra accuracy + if count >= threshold { + count += max // [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ + } + bitStream += uint32(count) << bitCount + bitCount += nbBits + if count < max { + bitCount-- + } + + previous0 = count == 1 + if remaining < 1 { + return errors.New("internal error: remaining<1") + } + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += (bitCount + 7) / 8 + + if uint16(charnum) > s.symbolLen { + return errors.New("internal error: charnum > s.symbolLen") + } + s.Out = out[:outP] + return nil +} + +// symbolTransform contains the state transform for a symbol. +type symbolTransform struct { + deltaFindState int32 + deltaNbBits uint32 +} + +// String prints values as a human readable string. +func (s symbolTransform) String() string { + return fmt.Sprintf("dnbits: %08x, fs:%d", s.deltaNbBits, s.deltaFindState) +} + +// cTable contains tables used for compression. +type cTable struct { + tableSymbol []byte + stateTable []uint16 + symbolTT []symbolTransform +} + +// allocCtable will allocate tables needed for compression. +// If existing tables a re big enough, they are simply re-used. +func (s *Scratch) allocCtable() { + tableSize := 1 << s.actualTableLog + // get tableSymbol that is big enough. + if cap(s.ct.tableSymbol) < int(tableSize) { + s.ct.tableSymbol = make([]byte, tableSize) + } + s.ct.tableSymbol = s.ct.tableSymbol[:tableSize] + + ctSize := tableSize + if cap(s.ct.stateTable) < ctSize { + s.ct.stateTable = make([]uint16, ctSize) + } + s.ct.stateTable = s.ct.stateTable[:ctSize] + + if cap(s.ct.symbolTT) < int(s.symbolLen) { + s.ct.symbolTT = make([]symbolTransform, 256) + } + s.ct.symbolTT = s.ct.symbolTT[:256] +} + +// buildCTable will populate the compression table so it is ready to be used. +func (s *Scratch) buildCTable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + var cumul [maxSymbolValue + 2]int16 + + s.allocCtable() + tableSymbol := s.ct.tableSymbol[:tableSize] + // symbol start positions + { + cumul[0] = 0 + for ui, v := range s.norm[:s.symbolLen-1] { + u := byte(ui) // one less than reference + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = u + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + } + // Encode last symbol separately to avoid overflowing u + u := int(s.symbolLen - 1) + v := s.norm[s.symbolLen-1] + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = byte(u) + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + if uint32(cumul[s.symbolLen]) != tableSize { + return fmt.Errorf("internal error: expected cumul[s.symbolLen] (%d) == tableSize (%d)", cumul[s.symbolLen], tableSize) + } + cumul[s.symbolLen] = int16(tableSize) + 1 + } + // Spread symbols + s.zeroBits = false + { + step := tableStep(tableSize) + tableMask := tableSize - 1 + var position uint32 + // if any symbol > largeLimit, we may have 0 bits output. + largeLimit := int16(1 << (s.actualTableLog - 1)) + for ui, v := range s.norm[:s.symbolLen] { + symbol := byte(ui) + if v > largeLimit { + s.zeroBits = true + } + for nbOccurrences := int16(0); nbOccurrences < v; nbOccurrences++ { + tableSymbol[position] = symbol + position = (position + step) & tableMask + for position > highThreshold { + position = (position + step) & tableMask + } /* Low proba area */ + } + } + + // Check if we have gone through all positions + if position != 0 { + return errors.New("position!=0") + } + } + + // Build table + table := s.ct.stateTable + { + tsi := int(tableSize) + for u, v := range tableSymbol { + // TableU16 : sorted by symbol order; gives next state value + table[cumul[v]] = uint16(tsi + u) + cumul[v]++ + } + } + + // Build Symbol Transformation Table + { + total := int16(0) + symbolTT := s.ct.symbolTT[:s.symbolLen] + tableLog := s.actualTableLog + tl := (uint32(tableLog) << 16) - (1 << tableLog) + for i, v := range s.norm[:s.symbolLen] { + switch v { + case 0: + case -1, 1: + symbolTT[i].deltaNbBits = tl + symbolTT[i].deltaFindState = int32(total - 1) + total++ + default: + maxBitsOut := uint32(tableLog) - highBits(uint32(v-1)) + minStatePlus := uint32(v) << maxBitsOut + symbolTT[i].deltaNbBits = (maxBitsOut << 16) - minStatePlus + symbolTT[i].deltaFindState = int32(total - v) + total += v + } + } + if total != int16(tableSize) { + return fmt.Errorf("total mismatch %d (got) != %d (want)", total, tableSize) + } + } + return nil +} + +// countSimple will create a simple histogram in s.count. +// Returns the biggest count. +// Does not update s.clearCount. +func (s *Scratch) countSimple(in []byte) (max int) { + for _, v := range in { + s.count[v]++ + } + m := uint32(0) + for i, v := range s.count[:] { + if v > m { + m = v + } + if v > 0 { + s.symbolLen = uint16(i) + 1 + } + } + return int(m) +} + +// minTableLog provides the minimum logSize to safely represent a distribution. +func (s *Scratch) minTableLog() uint8 { + minBitsSrc := highBits(uint32(s.br.remain()-1)) + 1 + minBitsSymbols := highBits(uint32(s.symbolLen-1)) + 2 + if minBitsSrc < minBitsSymbols { + return uint8(minBitsSrc) + } + return uint8(minBitsSymbols) +} + +// optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog +func (s *Scratch) optimalTableLog() { + tableLog := s.TableLog + minBits := s.minTableLog() + maxBitsSrc := uint8(highBits(uint32(s.br.remain()-1))) - 2 + if maxBitsSrc < tableLog { + // Accuracy can be reduced + tableLog = maxBitsSrc + } + if minBits > tableLog { + tableLog = minBits + } + // Need a minimum to safely represent all symbol values + if tableLog < minTablelog { + tableLog = minTablelog + } + if tableLog > maxTableLog { + tableLog = maxTableLog + } + s.actualTableLog = tableLog +} + +var rtbTable = [...]uint32{0, 473195, 504333, 520860, 550000, 700000, 750000, 830000} + +// normalizeCount will normalize the count of the symbols so +// the total is equal to the table size. +func (s *Scratch) normalizeCount() error { + var ( + tableLog = s.actualTableLog + scale = 62 - uint64(tableLog) + step = (1 << 62) / uint64(s.br.remain()) + vStep = uint64(1) << (scale - 20) + stillToDistribute = int16(1 << tableLog) + largest int + largestP int16 + lowThreshold = (uint32)(s.br.remain() >> tableLog) + ) + + for i, cnt := range s.count[:s.symbolLen] { + // already handled + // if (count[s] == s.length) return 0; /* rle special case */ + + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + stillToDistribute-- + } else { + proba := (int16)((uint64(cnt) * step) >> scale) + if proba < 8 { + restToBeat := vStep * uint64(rtbTable[proba]) + v := uint64(cnt)*step - (uint64(proba) << scale) + if v > restToBeat { + proba++ + } + } + if proba > largestP { + largestP = proba + largest = i + } + s.norm[i] = proba + stillToDistribute -= proba + } + } + + if -stillToDistribute >= (s.norm[largest] >> 1) { + // corner case, need another normalization method + return s.normalizeCount2() + } + s.norm[largest] += stillToDistribute + return nil +} + +// Secondary normalization method. +// To be used when primary method fails. +func (s *Scratch) normalizeCount2() error { + const notYetAssigned = -2 + var ( + distributed uint32 + total = uint32(s.br.remain()) + tableLog = s.actualTableLog + lowThreshold = uint32(total >> tableLog) + lowOne = uint32((total * 3) >> (tableLog + 1)) + ) + for i, cnt := range s.count[:s.symbolLen] { + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + distributed++ + total -= cnt + continue + } + if cnt <= lowOne { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + s.norm[i] = notYetAssigned + } + toDistribute := (1 << tableLog) - distributed + + if (total / toDistribute) > lowOne { + // risk of rounding to zero + lowOne = uint32((total * 3) / (toDistribute * 2)) + for i, cnt := range s.count[:s.symbolLen] { + if (s.norm[i] == notYetAssigned) && (cnt <= lowOne) { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + } + toDistribute = (1 << tableLog) - distributed + } + if distributed == uint32(s.symbolLen)+1 { + // all values are pretty poor; + // probably incompressible data (should have already been detected); + // find max, then give all remaining points to max + var maxV int + var maxC uint32 + for i, cnt := range s.count[:s.symbolLen] { + if cnt > maxC { + maxV = i + maxC = cnt + } + } + s.norm[maxV] += int16(toDistribute) + return nil + } + + if total == 0 { + // all of the symbols were low enough for the lowOne or lowThreshold + for i := uint32(0); toDistribute > 0; i = (i + 1) % (uint32(s.symbolLen)) { + if s.norm[i] > 0 { + toDistribute-- + s.norm[i]++ + } + } + return nil + } + + var ( + vStepLog = 62 - uint64(tableLog) + mid = uint64((1 << (vStepLog - 1)) - 1) + rStep = (((1 << vStepLog) * uint64(toDistribute)) + mid) / uint64(total) // scale on remaining + tmpTotal = mid + ) + for i, cnt := range s.count[:s.symbolLen] { + if s.norm[i] == notYetAssigned { + var ( + end = tmpTotal + uint64(cnt)*rStep + sStart = uint32(tmpTotal >> vStepLog) + sEnd = uint32(end >> vStepLog) + weight = sEnd - sStart + ) + if weight < 1 { + return errors.New("weight < 1") + } + s.norm[i] = int16(weight) + tmpTotal = end + } + } + return nil +} + +// validateNorm validates the normalized histogram table. +func (s *Scratch) validateNorm() (err error) { + var total int + for _, v := range s.norm[:s.symbolLen] { + if v >= 0 { + total += int(v) + } else { + total -= int(v) + } + } + defer func() { + if err == nil { + return + } + fmt.Printf("selected TableLog: %d, Symbol length: %d\n", s.actualTableLog, s.symbolLen) + for i, v := range s.norm[:s.symbolLen] { + fmt.Printf("%3d: %5d -> %4d \n", i, s.count[i], v) + } + }() + if total != (1 << s.actualTableLog) { + return fmt.Errorf("warning: Total == %d != %d", total, 1< tablelogAbsoluteMax { + return errors.New("tableLog too large") + } + bitStream >>= 4 + bitCount := uint(4) + + s.actualTableLog = uint8(nbBits) + remaining := int32((1 << nbBits) + 1) + threshold := int32(1 << nbBits) + gotTotal := int32(0) + nbBits++ + + for remaining > 1 { + if previous0 { + n0 := charnum + for (bitStream & 0xFFFF) == 0xFFFF { + n0 += 24 + if b.off < iend-5 { + b.advance(2) + bitStream = b.Uint32() >> bitCount + } else { + bitStream >>= 16 + bitCount += 16 + } + } + for (bitStream & 3) == 3 { + n0 += 3 + bitStream >>= 2 + bitCount += 2 + } + n0 += uint16(bitStream & 3) + bitCount += 2 + if n0 > maxSymbolValue { + return errors.New("maxSymbolValue too small") + } + for charnum < n0 { + s.norm[charnum&0xff] = 0 + charnum++ + } + + if b.off <= iend-7 || b.off+int(bitCount>>3) <= iend-4 { + b.advance(bitCount >> 3) + bitCount &= 7 + bitStream = b.Uint32() >> bitCount + } else { + bitStream >>= 2 + } + } + + max := (2*(threshold) - 1) - (remaining) + var count int32 + + if (int32(bitStream) & (threshold - 1)) < max { + count = int32(bitStream) & (threshold - 1) + bitCount += nbBits - 1 + } else { + count = int32(bitStream) & (2*threshold - 1) + if count >= threshold { + count -= max + } + bitCount += nbBits + } + + count-- // extra accuracy + if count < 0 { + // -1 means +1 + remaining += count + gotTotal -= count + } else { + remaining -= count + gotTotal += count + } + s.norm[charnum&0xff] = int16(count) + charnum++ + previous0 = count == 0 + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + if b.off <= iend-7 || b.off+int(bitCount>>3) <= iend-4 { + b.advance(bitCount >> 3) + bitCount &= 7 + } else { + bitCount -= (uint)(8 * (iend - 4 - b.off)) + b.off = iend - 4 + } + bitStream = b.Uint32() >> (bitCount & 31) + } + s.symbolLen = charnum + + if s.symbolLen <= 1 { + return fmt.Errorf("symbolLen (%d) too small", s.symbolLen) + } + if s.symbolLen > maxSymbolValue+1 { + return fmt.Errorf("symbolLen (%d) too big", s.symbolLen) + } + if remaining != 1 { + return fmt.Errorf("corruption detected (remaining %d != 1)", remaining) + } + if bitCount > 32 { + return fmt.Errorf("corruption detected (bitCount %d > 32)", bitCount) + } + if gotTotal != 1<> 3) + return nil +} + +// decSymbol contains information about a state entry, +// Including the state offset base, the output symbol and +// the number of bits to read for the low part of the destination state. +type decSymbol struct { + newState uint16 + symbol uint8 + nbBits uint8 +} + +// allocDtable will allocate decoding tables if they are not big enough. +func (s *Scratch) allocDtable() { + tableSize := 1 << s.actualTableLog + if cap(s.decTable) < int(tableSize) { + s.decTable = make([]decSymbol, tableSize) + } + s.decTable = s.decTable[:tableSize] + + if cap(s.ct.tableSymbol) < 256 { + s.ct.tableSymbol = make([]byte, 256) + } + s.ct.tableSymbol = s.ct.tableSymbol[:256] + + if cap(s.ct.stateTable) < 256 { + s.ct.stateTable = make([]uint16, 256) + } + s.ct.stateTable = s.ct.stateTable[:256] +} + +// buildDtable will build the decoding table. +func (s *Scratch) buildDtable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + s.allocDtable() + symbolNext := s.ct.stateTable[:256] + + // Init, lay down lowprob symbols + s.zeroBits = false + { + largeLimit := int16(1 << (s.actualTableLog - 1)) + for i, v := range s.norm[:s.symbolLen] { + if v == -1 { + s.decTable[highThreshold].symbol = uint8(i) + highThreshold-- + symbolNext[i] = 1 + } else { + if v >= largeLimit { + s.zeroBits = true + } + symbolNext[i] = uint16(v) + } + } + } + // Spread symbols + { + tableMask := tableSize - 1 + step := tableStep(tableSize) + position := uint32(0) + for ss, v := range s.norm[:s.symbolLen] { + for i := 0; i < int(v); i++ { + s.decTable[position].symbol = uint8(ss) + position = (position + step) & tableMask + for position > highThreshold { + // lowprob area + position = (position + step) & tableMask + } + } + } + if position != 0 { + // position must reach all cells once, otherwise normalizedCounter is incorrect + return errors.New("corrupted input (position != 0)") + } + } + + // Build Decoding table + { + tableSize := uint16(1 << s.actualTableLog) + for u, v := range s.decTable { + symbol := v.symbol + nextState := symbolNext[symbol] + symbolNext[symbol] = nextState + 1 + nBits := s.actualTableLog - byte(highBits(uint32(nextState))) + s.decTable[u].nbBits = nBits + newState := (nextState << nBits) - tableSize + if newState > tableSize { + return fmt.Errorf("newState (%d) outside table size (%d)", newState, tableSize) + } + if newState == uint16(u) && nBits == 0 { + // Seems weird that this is possible with nbits > 0. + return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, u) + } + s.decTable[u].newState = newState + } + } + return nil +} + +// decompress will decompress the bitstream. +// If the buffer is over-read an error is returned. +func (s *Scratch) decompress() error { + br := &s.bits + br.init(s.br.unread()) + + var s1, s2 decoder + // Initialize and decode first state and symbol. + s1.init(br, s.decTable, s.actualTableLog) + s2.init(br, s.decTable, s.actualTableLog) + + // Use temp table to avoid bound checks/append penalty. + var tmp = s.ct.tableSymbol[:256] + var off uint8 + + // Main part + if !s.zeroBits { + for br.off >= 8 { + br.fillFast() + tmp[off+0] = s1.nextFast() + tmp[off+1] = s2.nextFast() + br.fillFast() + tmp[off+2] = s1.nextFast() + tmp[off+3] = s2.nextFast() + off += 4 + if off == 0 { + s.Out = append(s.Out, tmp...) + } + } + } else { + for br.off >= 8 { + br.fillFast() + tmp[off+0] = s1.next() + tmp[off+1] = s2.next() + br.fillFast() + tmp[off+2] = s1.next() + tmp[off+3] = s2.next() + off += 4 + if off == 0 { + s.Out = append(s.Out, tmp...) + off = 0 + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } + } + } + } + s.Out = append(s.Out, tmp[:off]...) + + // Final bits, a bit more expensive check + for { + if s1.finished() { + s.Out = append(s.Out, s1.final(), s2.final()) + break + } + br.fill() + s.Out = append(s.Out, s1.next()) + if s2.finished() { + s.Out = append(s.Out, s2.final(), s1.final()) + break + } + s.Out = append(s.Out, s2.next()) + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } + } + return br.close() +} + +// decoder keeps track of the current state and updates it from the bitstream. +type decoder struct { + state uint16 + br *bitReader + dt []decSymbol +} + +// init will initialize the decoder and read the first state from the stream. +func (d *decoder) init(in *bitReader, dt []decSymbol, tableLog uint8) { + d.dt = dt + d.br = in + d.state = uint16(in.getBits(tableLog)) +} + +// next returns the next symbol and sets the next state. +// At least tablelog bits must be available in the bit reader. +func (d *decoder) next() uint8 { + n := &d.dt[d.state] + lowBits := d.br.getBits(n.nbBits) + d.state = n.newState + lowBits + return n.symbol +} + +// finished returns true if all bits have been read from the bitstream +// and the next state would require reading bits from the input. +func (d *decoder) finished() bool { + return d.br.finished() && d.dt[d.state].nbBits > 0 +} + +// final returns the current state symbol without decoding the next. +func (d *decoder) final() uint8 { + return d.dt[d.state].symbol +} + +// nextFast returns the next symbol and sets the next state. +// This can only be used if no symbols are 0 bits. +// At least tablelog bits must be available in the bit reader. +func (d *decoder) nextFast() uint8 { + n := d.dt[d.state] + lowBits := d.br.getBitsFast(n.nbBits) + d.state = n.newState + lowBits + return n.symbol +} diff --git a/vendor/github.com/klauspost/compress/fse/fse.go b/vendor/github.com/klauspost/compress/fse/fse.go new file mode 100644 index 0000000..57cfda3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fse.go @@ -0,0 +1,138 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +// Package fse provides Finite State Entropy encoding and decoding. +// +// Finite State Entropy encoding provides a fast near-optimal symbol encoding/decoding +// for byte blocks as implemented in zstd. +// +// See https://github.com/klauspost/compress/tree/master/fse for more information. +package fse + +import ( + "errors" + "fmt" +) + +const ( + /*!MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ + maxMemoryUsage = 14 + defaultMemoryUsage = 13 + + maxTableLog = maxMemoryUsage - 2 + maxTablesize = 1 << maxTableLog + defaultTablelog = defaultMemoryUsage - 2 + minTablelog = 5 + maxSymbolValue = 255 +) + +var ( + // ErrIncompressible is returned when input is judged to be too hard to compress. + ErrIncompressible = errors.New("input is not compressible") + + // ErrUseRLE is returned from the compressor when the input is a single byte value repeated. + ErrUseRLE = errors.New("input is single value repeated") +) + +// Scratch provides temporary storage for compression and decompression. +type Scratch struct { + // Private + count [maxSymbolValue + 1]uint32 + norm [maxSymbolValue + 1]int16 + symbolLen uint16 // Length of active part of the symbol table. + actualTableLog uint8 // Selected tablelog. + br byteReader + bits bitReader + bw bitWriter + ct cTable // Compression tables. + decTable []decSymbol // Decompression table. + zeroBits bool // no bits has prob > 50%. + clearCount bool // clear count + maxCount int // count of the most probable symbol + + // Per block parameters. + // These can be used to override compression parameters of the block. + // Do not touch, unless you know what you are doing. + + // Out is output buffer. + // If the scratch is re-used before the caller is done processing the output, + // set this field to nil. + // Otherwise the output buffer will be re-used for next Compression/Decompression step + // and allocation will be avoided. + Out []byte + + // MaxSymbolValue will override the maximum symbol value of the next block. + MaxSymbolValue uint8 + + // TableLog will attempt to override the tablelog for the next block. + TableLog uint8 + + // DecompressLimit limits the maximum decoded size acceptable. + // If > 0 decompression will stop when approximately this many bytes + // has been decoded. + // If 0, maximum size will be 2GB. + DecompressLimit int +} + +// Histogram allows to populate the histogram and skip that step in the compression, +// It otherwise allows to inspect the histogram when compression is done. +// To indicate that you have populated the histogram call HistogramFinished +// with the value of the highest populated symbol, as well as the number of entries +// in the most populated entry. These are accepted at face value. +// The returned slice will always be length 256. +func (s *Scratch) Histogram() []uint32 { + return s.count[:] +} + +// HistogramFinished can be called to indicate that the histogram has been populated. +// maxSymbol is the index of the highest set symbol of the next data segment. +// maxCount is the number of entries in the most populated entry. +// These are accepted at face value. +func (s *Scratch) HistogramFinished(maxSymbol uint8, maxCount int) { + s.maxCount = maxCount + s.symbolLen = uint16(maxSymbol) + 1 + s.clearCount = maxCount != 0 +} + +// prepare will prepare and allocate scratch tables used for both compression and decompression. +func (s *Scratch) prepare(in []byte) (*Scratch, error) { + if s == nil { + s = &Scratch{} + } + if s.MaxSymbolValue == 0 { + s.MaxSymbolValue = 255 + } + if s.TableLog == 0 { + s.TableLog = defaultTablelog + } + if s.TableLog > maxTableLog { + return nil, fmt.Errorf("tableLog (%d) > maxTableLog (%d)", s.TableLog, maxTableLog) + } + if cap(s.Out) == 0 { + s.Out = make([]byte, 0, len(in)) + } + if s.clearCount && s.maxCount == 0 { + for i := range s.count { + s.count[i] = 0 + } + s.clearCount = false + } + s.br.init(in) + if s.DecompressLimit == 0 { + // Max size 2GB. + s.DecompressLimit = 2 << 30 + } + + return s, nil +} + +// tableStep returns the next table index. +func tableStep(tableSize uint32) uint32 { + return (tableSize >> 1) + (tableSize >> 3) + 3 +} diff --git a/vendor/github.com/klauspost/compress/fse/fse_test.go b/vendor/github.com/klauspost/compress/fse/fse_test.go new file mode 100644 index 0000000..5407d26 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fse_test.go @@ -0,0 +1,310 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" +) + +type inputFn func() ([]byte, error) + +var testfiles = []struct { + name string + fn inputFn + err error +}{ + // gettysburg.txt is a small plain text. + {name: "gettysburg", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/gettysburg.txt") }}, + // Digits is the digits of the irrational number e. Its decimal representation + // does not repeat, but there are only 10 possible digits, so it should be + // reasonably compressible. + {name: "digits", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/e.txt") }}, + // Twain is Project Gutenberg's edition of Mark Twain's classic English novel. + {name: "twain", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt") }}, + // Random bytes + {name: "random", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/sharnd.out") }, err: ErrIncompressible}, + // Low entropy + {name: "low-ent", fn: func() ([]byte, error) { return []byte(strings.Repeat("1221", 10000)), nil }}, + // Super Low entropy + {name: "superlow-ent", fn: func() ([]byte, error) { return []byte(strings.Repeat("1", 10000) + strings.Repeat("2", 500)), nil }}, + // Zero bytes + {name: "zeroes", fn: func() ([]byte, error) { return make([]byte, 10000), nil }, err: ErrUseRLE}, + {name: "crash1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash1.bin") }, err: ErrIncompressible}, + {name: "crash2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash2.bin") }, err: ErrIncompressible}, + {name: "crash3", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash3.bin") }, err: ErrIncompressible}, + {name: "endzerobits", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/endzerobits.bin") }, err: nil}, + {name: "endnonzero", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/endnonzero.bin") }, err: ErrIncompressible}, + {name: "case1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case1.bin") }, err: ErrIncompressible}, + {name: "case2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case2.bin") }, err: ErrIncompressible}, + {name: "case3", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case3.bin") }, err: ErrIncompressible}, + {name: "pngdata.001", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/pngdata.bin") }, err: nil}, + {name: "normcount2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/normcount2.bin") }, err: nil}, +} + +var decTestfiles = []struct { + name string + fn inputFn + err string +}{ + // gettysburg.txt is a small plain text. + {name: "hang1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/dec-hang1.bin") }, err: "corruption detected (bitCount 252 > 32)"}, + {name: "hang2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/dec-hang2.bin") }, err: "newState (0) == oldState (0) and no bits"}, + {name: "hang3", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/dec-hang3.bin") }, err: "maxSymbolValue too small"}, + {name: "symlen1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/dec-symlen1.bin") }, err: "symbolLen (257) too big"}, + {name: "crash4", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash4.bin") }, err: "symbolLen (1) too small"}, + {name: "crash5", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash5.bin") }, err: "symbolLen (1) too small"}, +} + +func TestCompress(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s Scratch + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + b, err := Compress(buf0, &s) + if err != test.err { + t.Errorf("want error %v (%T), got %v (%T)", test.err, test.err, err, err) + } + if b == nil { + t.Log(test.name + ": not compressible") + return + } + t.Logf("%s: %d -> %d bytes (%.2f:1)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b))) + }) + } +} + +func ExampleCompress() { + // Read data + data, err := ioutil.ReadFile("../testdata/e.txt") + if err != nil { + panic(err) + } + + // Create re-usable scratch buffer. + var s Scratch + b, err := Compress(data, &s) + if err != nil { + panic(err) + } + fmt.Printf("Compress: %d -> %d bytes (%.2f:1)\n", len(data), len(b), float64(len(data))/float64(len(b))) + // OUTPUT: Compress: 100003 -> 41564 bytes (2.41:1) +} + +func TestDecompress(t *testing.T) { + for _, test := range decTestfiles { + t.Run(test.name, func(t *testing.T) { + var s Scratch + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + b, err := Decompress(buf0, &s) + if fmt.Sprint(err) != test.err { + t.Errorf("want error %q, got %q (%T)", test.err, err, err) + return + } + if err != nil { + return + } + if len(b) == 0 { + t.Error(test.name + ": no output") + return + } + t.Logf("%s: %d -> %d bytes (1:%.2f)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b))) + }) + } +} + +func ExampleDecompress() { + // Read data + data, err := ioutil.ReadFile("../testdata/e.txt") + if err != nil { + panic(err) + } + + // Create re-usable scratch buffer. + var s Scratch + b, err := Compress(data, &s) + if err != nil { + panic(err) + } + + // Since we use the output of compression, it cannot be used as output for decompression. + s.Out = make([]byte, 0, len(data)) + d, err := Decompress(b, &s) + if err != nil { + panic(err) + } + fmt.Printf("Input matches: %t\n", bytes.Equal(d, data)) + // OUTPUT: Input matches: true +} + +func TestGenCorpus(t *testing.T) { + t.Skip("only for generating decompress corpus") + filepath.Walk("fuzz/compress/corpus", func(path string, info os.FileInfo, err error) error { + t.Run(path, func(t *testing.T) { + var s Scratch + buf0, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + b, err := Compress(buf0, &s) + if err != nil { + t.Skip("skipping") + return + } + t.Logf("%s: %d -> %d bytes (%.2f:1)", path, len(buf0), len(b), float64(len(buf0))/float64(len(b))) + dstP := strings.Replace(path, "compress", "decompress", 1) + ioutil.WriteFile(dstP, b, os.ModePerm) + }) + return nil + }) +} + +func BenchmarkCompress(b *testing.B) { + for _, tt := range testfiles { + test := tt + b.Run(test.name, func(b *testing.B) { + var s Scratch + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + _, err = Compress(buf0, &s) + if err != test.err { + b.Fatal("unexpected error:", err) + } + if err != nil { + b.Skip("skipping benchmark: ", err) + return + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, _ = Compress(buf0, &s) + } + }) + } +} + +func TestReadNCount(t *testing.T) { + for i := range testfiles { + var s Scratch + test := testfiles[i] + t.Run(test.name, func(t *testing.T) { + name := test.name + ": " + buf0, err := testfiles[i].fn() + if err != nil { + t.Fatal(err) + } + b, err := Compress(buf0, &s) + if err != test.err { + t.Error(err) + return + } + if err != nil { + t.Skip(name + err.Error()) + return + } + t.Logf("%s: %d -> %d bytes (%.2f:1)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b))) + //t.Logf("%v", b) + var s2 Scratch + dc, err := Decompress(b, &s2) + if err != nil { + t.Fatal(err) + } + want := s.norm[:s.symbolLen] + got := s2.norm[:s2.symbolLen] + if !cmp.Equal(want, got) { + if s.actualTableLog != s2.actualTableLog { + t.Errorf(name+"norm table, want tablelog: %d, got %d", s.actualTableLog, s2.actualTableLog) + } + if s.symbolLen != s2.symbolLen { + t.Errorf(name+"norm table, want size: %d, got %d", s.symbolLen, s2.symbolLen) + } + t.Errorf(name+"norm table, got delta: \n%s", cmp.Diff(want, got)) + return + } + for i, dec := range s2.decTable { + dd := dec.symbol + ee := s.ct.tableSymbol[i] + if dd != ee { + t.Errorf("table symbol mismatch. idx %d, enc: %v, dec:%v", i, ee, dd) + break + } + } + if dc != nil { + if len(buf0) != len(dc) { + t.Errorf(name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) + if len(buf0) > len(dc) { + buf0 = buf0[:len(dc)] + } else { + dc = dc[:len(buf0)] + } + if !cmp.Equal(buf0, dc) { + t.Errorf(name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) + } + return + } + if !cmp.Equal(buf0, dc) { + t.Errorf(name+"decompressed, got delta: \n%s", cmp.Diff(buf0, dc)) + } + if !t.Failed() { + t.Log("... roundtrip ok!") + } + } + }) + } +} + +func BenchmarkDecompress(b *testing.B) { + for _, tt := range testfiles { + test := tt + b.Run(test.name, func(b *testing.B) { + var s, s2 Scratch + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + out, err := Compress(buf0, &s) + if err != test.err { + b.Fatal(err) + } + if err != nil { + b.Skip(test.name + ": " + err.Error()) + return + } + got, err := Decompress(out, &s2) + if err != nil { + b.Fatal(err) + } + if !bytes.Equal(buf0, got) { + b.Fatal("output mismatch") + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, err = Decompress(out, &s2) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff new file mode 100644 index 0000000000000000000000000000000000000000..7b6ae9e60728f7b49f5488f59e732570f6d2f61c GIT binary patch literal 10001 zcmeHNOK;Oa5U#`xapS@Pp>jdu&}wJjdjOHxF={E|5n7-JM)3;*Z5odjD{Oyo@agdL@aQ80`fJ@^Tms-)cBmK0LoRJoWgIZk?R@{dbt1X!(frJpK+!#wY z5~>OkHVhgpXap{FF-;f*)}*0pHoT7L1eynaC$e-8mx<_r4}N0(2ZQYHmn?%vApu`* zBk^DeE2%-qL~8Qi#MVv@UhI8HdTYIOZ-2LQ&?P#Y(PkiAo*|wt&0vPf6U;#Pxztx@ z!C!%%0vXpVu0N0Rh@Nai1)(#i$fZ=K`QhQ&Sut^nq6NA*xQqsr^q(^WDh{4k9?=FN z{*J6=@Qb5zJpY~a{~QWM^{cDhMH_HQm{jwqOd=Z1S0L0p8s%QaaGo;34ii6){WNw- zpgr>I6n~rUE_RZ6t3RdQQ_7=ipjLKN7fpri4^&5`6dQUi7lxtqBj3}FR%+w48F`_M zmNn&m2Re|4-B-Bt7F*cuGd%jFdfq^*qdYH!jrIO^Uf#hbL%`Q)cbinlq1Qq!(IL9e z>uIt{#orcMG*2GOt)-J(fr`^T# zc7CKYyLG#QPrYiKQm53b;Isg%M$My=gMSTv>*-%t$2xTuQ?Ey3q{x4$d363)73zI$ foJuv1&c`D{aEf!5{Qal;#AEsskNh>Re}e3H2P&fU literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/00f14dd34076a71e9e54b9b88497c2a214c91d81-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/00f14dd34076a71e9e54b9b88497c2a214c91d81-3 new file mode 100644 index 0000000..b1f7368 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/00f14dd34076a71e9e54b9b88497c2a214c91d81-3 @@ -0,0 +1 @@ +c|W 0^&B55548270565|n|ne \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/01a027e4ad99a383228779f2aaf1a2f4a3f3857b-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/01a027e4ad99a383228779f2aaf1a2f4a3f3857b-3 new file mode 100644 index 0000000..85c9468 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/01a027e4ad99a383228779f2aaf1a2f4a3f3857b-3 @@ -0,0 +1 @@ +||l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/028b20cc463cb40889c44f46b67d13db0c6b50a2-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/028b20cc463cb40889c44f46b67d13db0c6b50a2-2 new file mode 100644 index 0000000..7962902 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/028b20cc463cb40889c44f46b67d13db0c6b50a2-2 @@ -0,0 +1 @@ +|u|l888178419700125232338905334425pc⃀?n \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/02a4a6eccf33f032b9acc928be2f5377b31d0b03-11 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/02a4a6eccf33f032b9acc928be2f5377b31d0b03-11 new file mode 100644 index 0000000..d93ae70 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/02a4a6eccf33f032b9acc928be2f5377b31d0b03-11 @@ -0,0 +1 @@ +c|W 70^&B55555554827056640123456789abcdefghijklmnpq828V12-0rstuvwxyz]=!(BADPREC)68@'E>103ĉs){1Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 new file mode 100644 index 0000000..b0b2408 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 @@ -0,0 +1 @@ +--)!)')44441402363-40e1a8Aea03B00161__1A-!_1________8)-0414'' \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 new file mode 100644 index 0000000..014b508 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 @@ -0,0 +1 @@ +24055111512312578270211815834045410156250650722545140161410432351365152036224040CE3BdA64ABbeDddDfd9eF6C55511151231257827021181583404� 54101562555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABf82208f6CDcE92fbE6 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0b0a852a4680d8f3fe07ad0e9997b18186918c78-10 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0b0a852a4680d8f3fe07ad0e9997b18186918c78-10 new file mode 100644 index 0000000..2175b8e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0b0a852a4680d8f3fe07ad0e9997b18186918c78-10 @@ -0,0 +1 @@ +c|W 7%B5S0123456789 ~1 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 new file mode 100644 index 0000000..e9d048c --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 @@ -0,0 +1 @@ +<55555555559 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c851d4e4c8b5055b6ce3b68089892203057b3c0-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c851d4e4c8b5055b6ce3b68089892203057b3c0-4 new file mode 100644 index 0000000..a3e7612 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0c851d4e4c8b5055b6ce3b68089892203057b3c0-4 @@ -0,0 +1 @@ +|pW2zu| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0d0de3f34f3d27f32d12be358cb2dde550d72172 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0d0de3f34f3d27f32d12be358cb2dde550d72172 new file mode 100644 index 0000000000000000000000000000000000000000..cc4e4242c45fc573b2bb92e766846853754dbdba GIT binary patch literal 63 zcmY$Wh;FdjE|2uh)**q^eXpDkB>JriA;{S@DC0Pu8OaSH!X~3 S&^0hMHZd_W(9^ZBWB>qzq!OwC literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 new file mode 100644 index 0000000..3ea2a9f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 @@ -0,0 +1 @@ +2555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABbeDddDfd9eF6C55511151231257827021181583404� 54101562555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABf82208f6CDc \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/110c8a30c16070bf2813480d9492a1a170a7d80a-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/110c8a30c16070bf2813480d9492a1a170a7d80a-4 new file mode 100644 index 0000000..ce6bfe6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/110c8a30c16070bf2813480d9492a1a170a7d80a-4 @@ -0,0 +1 @@ +ll \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/138deac60e8494cd0329602411774ea9ba629f72-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/138deac60e8494cd0329602411774ea9ba629f72-6 new file mode 100644 index 0000000..ed848aa --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/138deac60e8494cd0329602411774ea9ba629f72-6 @@ -0,0 +1 @@ +4651953614188823848962783813 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/19aa2a437fa2a48199cc0294469a0a942ae1483a-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/19aa2a437fa2a48199cc0294469a0a942ae1483a-4 new file mode 100644 index 0000000..c103e68 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/19aa2a437fa2a48199cc0294469a0a942ae1483a-4 @@ -0,0 +1 @@ +5555555555555555555555555555555555555555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1b6cc66a7d78b5b1f37a7d4d7efaaeed1a6ce630-9 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1b6cc66a7d78b5b1f37a7d4d7efaaeed1a6ce630-9 new file mode 100644 index 0000000..82fb807 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1b6cc66a7d78b5b1f37a7d4d7efaaeed1a6ce630-9 @@ -0,0 +1 @@ +c|W 7%B5S0123456789abcdefghijklmnpqrstuvwxyz]=!(BADPREC)68@'E>1031Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1bf17f213e2aee50a14d920aa1c615edab1b4d11 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1bf17f213e2aee50a14d920aa1c615edab1b4d11 new file mode 100644 index 0000000..837483c --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1bf17f213e2aee50a14d920aa1c615edab1b4d11 @@ -0,0 +1 @@ +-86840441164045277856725051e0xFA0FAF9b9dd1FFF87fb9BACa3aF62FDac8 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1cfd49b23106a3de30052a18cee3bed23d08f552-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1cfd49b23106a3de30052a18cee3bed23d08f552-7 new file mode 100644 index 0000000..2ab3ea1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1cfd49b23106a3de30052a18cee3bed23d08f552-7 @@ -0,0 +1 @@ +c|pW s%!(BADPREC)5?h睙63837019buo�lo \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1ecd000fbf02c3bd4cf7cfa7a314580789536ab0-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1ecd000fbf02c3bd4cf7cfa7a314580789536ab0-3 new file mode 100644 index 0000000..6e3352f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1ecd000fbf02c3bd4cf7cfa7a314580789536ab0-3 @@ -0,0 +1 @@ +c|pW2zu| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f2a2c8867dce3ed56fef849e5de664c20cdae39-10 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f2a2c8867dce3ed56fef849e5de664c20cdae39-10 new file mode 100644 index 0000000..b64d627 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f2a2c8867dce3ed56fef849e5de664c20cdae39-10 @@ -0,0 +1 @@ +c|W 7%B4827056640123456789abcdefghijklmnpqrstuvwxyz]=!(BADPREC)68@'E>103ĉs){1Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f969240d093a413365023cc05432790a500046a-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/1f969240d093a413365023cc05432790a500046a-1 new file mode 100644 index 0000000000000000000000000000000000000000..444c24fa57ab12ff6e9f0703b8d60878bf890dc4 GIT binary patch literal 52 zcmWN<%MAb!5CuS2#gKh#zbCzjs6qK;rWU{$hFzwCtp{6{vXoQsS|Pd0L1HTt5O#qY99s} literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 new file mode 100644 index 0000000000000000000000000000000000000000..06089b9d81b8f03576b75ebdd8280c183f894413 GIT binary patch literal 1064 zcmeHF%TB^j5bdY*2TbO^Z`~;*P!Os>1l*k1auukwq{S4BA8)%M(WDC#7A~C4Ofo0u zoO$?uRC+#RLTf9G;Y_oY=X+PgwIjw2<60X=k_#b7YBEGpa3W$_Yeh;CdDowI*@w;X zan~6GGDBxwrznWmJ)~AJ3uqMR0Rf^VVa8V~3^x_AQ;jPPEw+S!4S`8Mz_G?P5n2o; z3E-gGLy}aSncAwFA(|tIhy5+LkGH6(W3h)p o5i86=I6l1%&st644);Z#xUw9%U0$4;zxvHTHWc5l_eTl80Jw4zRR910 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/283e76a3a5ac43d02ad685c555a6eb9a8fbe88e5-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/283e76a3a5ac43d02ad685c555a6eb9a8fbe88e5-4 new file mode 100644 index 0000000..3b36f31 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/283e76a3a5ac43d02ad685c555a6eb9a8fbe88e5-4 @@ -0,0 +1 @@ +c||nm flag fieldu \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/284e42ad2dbdfcfb6c7e6c7d5ad1bcc7e911f96f-10 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/284e42ad2dbdfcfb6c7e6c7d5ad1bcc7e911f96f-10 new file mode 100644 index 0000000..c5a987a --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/284e42ad2dbdfcfb6c7e6c7d5ad1bcc7e911f96f-10 @@ -0,0 +1 @@ +|W %S0123479abcdefghijklmnopqrstuvwxyzソ]=!(BADPREC)568@' \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2891dddca25448c8f1671b9779f715b45e6ebef0-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2891dddca25448c8f1671b9779f715b45e6ebef0-3 new file mode 100644 index 0000000..4d9f423 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2891dddca25448c8f1671b9779f715b45e6ebef0-3 @@ -0,0 +1 @@ +|u| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2b8284f1553bb6e799466377047fff8a30e1dba0-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2b8284f1553bb6e799466377047fff8a30e1dba0-6 new file mode 100644 index 0000000..03caa51 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2b8284f1553bb6e799466377047fff8a30e1dba0-6 @@ -0,0 +1 @@ +c|pW s')0567819432u| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2c3a94ad7435a7c8ae24df733e7c3a1044b38580-10 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2c3a94ad7435a7c8ae24df733e7c3a1044b38580-10 new file mode 100644 index 0000000..ad723eb --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/2c3a94ad7435a7c8ae24df733e7c3a1044b38580-10 @@ -0,0 +1 @@ +\W 7%B8673617379884035472059622406959533691406255S0123456789abcdefghijklmnpqrstuvwxyz]=!(BADPREC)68@'E>1031Kboo� \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 new file mode 100644 index 0000000000000000000000000000000000000000..43b96595474c3421513cf9887e7d363e7adabbab GIT binary patch literal 62 zcmWm4yA6Oa3cMia!qAXJpnB%c%1%)CI(`vTUUEA>| M)_uuJedia)27B8K<^TWy literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 new file mode 100644 index 0000000..3757a05 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 @@ -0,0 +1 @@ +55555555559 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 new file mode 100644 index 0000000000000000000000000000000000000000..1afa5a8b9952d75ab80b5e8f9ac99467221be1fb GIT binary patch literal 12 LcmZQzWPk$z02crP literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33d53df606943afe544548920b1b8bd3e1ecf731-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33d53df606943afe544548920b1b8bd3e1ecf731-7 new file mode 100644 index 0000000..185cf20 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/33d53df606943afe544548920b1b8bd3e1ecf731-7 @@ -0,0 +1 @@ +f|W s'p)05678too few operands for format '%19432u2 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3473974824e5391343390e25b1e250edf2ab45cf-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3473974824e5391343390e25b1e250edf2ab45cf-6 new file mode 100644 index 0000000000000000000000000000000000000000..128a0f0dbe4f79b0d649fb4e8c8d37c5925be8e8 GIT binary patch literal 5 McmZQ(U|?hf000*N1^@s6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/393fe96068641f74607dd7eebde0807de355944a-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/393fe96068641f74607dd7eebde0807de355944a-2 new file mode 100644 index 0000000..d9aa457 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/393fe96068641f74607dd7eebde0807de355944a-2 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ac84d808844f1204e0704eb2d87a083d17e5edf-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ac84d808844f1204e0704eb2d87a083d17e5edf-4 new file mode 100644 index 0000000000000000000000000000000000000000..1d118e0e976163ad56174ba9f2369b7a9a9a5181 GIT binary patch literal 29 kcmY!|G&DA|Ftac=H#aggGfZKyG&Z-iurRVPG%{rX09OJ9uK)l5 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 new file mode 100644 index 0000000..d64bff4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 @@ -0,0 +1 @@ +5555555555555etProcessMemoryInfo5217012461354e46015555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ca5ae6d9b3a1d465c8214e272c32a60ebc0c848-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ca5ae6d9b3a1d465c8214e272c32a60ebc0c848-2 new file mode 100644 index 0000000..542906e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3ca5ae6d9b3a1d465c8214e272c32a60ebc0c848-2 @@ -0,0 +1 @@ +55511151225 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 new file mode 100644 index 0000000..ed669c0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 @@ -0,0 +1 @@ +555111512312578270211815834045410156250xD9beDddDfd9eF6C5551115123125782702118158340454101562555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABf82208f6CDcE92fbE6F \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 new file mode 100644 index 0000000000000000000000000000000000000000..20d5cb86e6dff1f3684dc229a358a2ea697cecfb GIT binary patch literal 8 KcmZQ%fB*mh5C8%I literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d new file mode 100644 index 0000000000000000000000000000000000000000..24adff12b16f25cf20ca9957e3a1fb9bc1ad6a35 GIT binary patch literal 583 zcmdUsyKciU3`PAZ`GEu^C5p;cDT<0d(82-w$|5+HoVH65_W^%?l?bLe62x%M#7%JnXzHFbqP(no&b_ zs-;?y;ws9>1j-OqnHtRiZ@Q(l+jjGjQrfe?Yn#UF)HDsiNfucH1JJRW1o^}pqtJlj z1x&Io*%5Yz4M@mwh~$xD7yew2=s((I4pLuLU}B7&b)^I4chGxrE|lOE=diP}AAEqk zS`Tx7f0xGe?A}xQdfdv(5Ip!g<{`iB(;1031Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 new file mode 100644 index 0000000..3b927e2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/40259a0dccc3648661894e1cb9d43ecb18c1e94f-4 @@ -0,0 +1 @@ +||346519536141888238489627838134765(25l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 new file mode 100644 index 0000000..7b6e0bb --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 @@ -0,0 +1 @@ +55555555555555555545555 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/44a33b09be4119510e06b8cf5f695658dd0da430-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/44a33b09be4119510e06b8cf5f695658dd0da430-3 new file mode 100644 index 0000000..2f4d368 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/44a33b09be4119510e06b8cf5f695658dd0da430-3 @@ -0,0 +1 @@ +c|n|name flag fieldu \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/463d78c147df54fb78e55f52f79c9dff7a42c5c3-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/463d78c147df54fb78e55f52f79c9dff7a42c5c3-4 new file mode 100644 index 0000000..828c846 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/463d78c147df54fb78e55f52f79c9dff7a42c5c3-4 @@ -0,0 +1 @@ +c|pW 2zu| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a076c6a1ff5c3956d52a9a18c90636d9271d5dc-8 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a076c6a1ff5c3956d52a9a18c90636d9271d5dc-8 new file mode 100644 index 0000000..d50965b --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a076c6a1ff5c3956d52a9a18c90636d9271d5dc-8 @@ -0,0 +1 @@ +c|W s%B�5S奔ソ]=!(BADPREC)568@'E>17031Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd new file mode 100644 index 0000000..1ed2a7e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd @@ -0,0 +1 @@ +5555555555555555555555555555554045217012461354e46015555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4c2d1f5dfeb5273fe3c44edc2c9b016159d23b5c-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4c2d1f5dfeb5273fe3c44edc2c9b016159d23b5c-3 new file mode 100644 index 0000000..b12fa85 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4c2d1f5dfeb5273fe3c44edc2c9b016159d23b5c-3 @@ -0,0 +1 @@ +55511110156 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 new file mode 100644 index 0000000..87c2df5 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 @@ -0,0 +1 @@ +5555555555555555555555555 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 new file mode 100644 index 0000000000000000000000000000000000000000..1397e77b63d77edbbb851033dc9ff9e3873495f4 GIT binary patch literal 307 zcma)&L25!l5JcxFULc{nr@LonlSTXnLb6C0M3PN`&JQT&=MzE1(>q6ST~*ZMEtsQc z&oL!o=N3YEAW|}yM z6`XZXE1b(oYVm8rH)bmz>xy9p{;}IE|E8x9%#4|hC9+t`l1P{{TaHR<%ETSVIz`!z nLuPQQVw8vfXJ4}WyfZg z+|c@1*g@+0QuB5rqnzk2@;Y4Xxi|(Ekw>~+)C&%B5vl+H literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6548f73fac595761f3cf335b35d1ff524d67f09f-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6548f73fac595761f3cf335b35d1ff524d67f09f-5 new file mode 100644 index 0000000000000000000000000000000000000000..82c74a0bc1588c72e8ba45710e650a4c0203be26 GIT binary patch literal 32 ncmY!|G&DA|Ftac=H#aggGfZJ%U~n)tHn+5}FtRW-GGzb&WE}!aQF~z`dOu$*nYr!695Od7kBkVByB*k?xT+x!B`hsl(zPJsW PPbDIY9?f%>%#!F2&i*69 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 new file mode 100644 index 0000000000000000000000000000000000000000..56b5a0f93714b7c34f98608647f033323759254e GIT binary patch literal 1817 zcmeH{yGjHx6o%(f_6g)%a&jr18;BOluq@gf+(`x$9S0YdVV~YuXeXqz*ez0>*fGttJGmol5U=FoUZH(;{L+Wi)cC2g{6sIlZUBdpjRP?e{R<5gQYObfI?)$o) zTtjh;={b%mNZ%#1*7AjU%h2B|aC)s5u35c2DDx=Ptv literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b99950532c007f8f24725686d8142ddf390889b b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/6b99950532c007f8f24725686d8142ddf390889b new file mode 100644 index 0000000000000000000000000000000000000000..6b5168872e164e036fadc5f6fb012a182bd99f29 GIT binary patch literal 1303 zcmeH`&q~8U5XSQ;eSwyl*`3|wX13c%QT!KbZ7)NTO{7I@ZM6iS-t{7QD|oTsZD3~j zzWJEn08yFLq{>=CgCR*0(7@KP0c{QTzSiYJ$jyzuFf%E`rkAz8+=xgkq7>k>>_u*= zeEN{7$X3W^a?mT7$RXQPnVAnOOWAUEGb_b!MRwB6$1j_o!pw|_jHHm*reuK-Q{+@> z(5w-V4KegSt6Lv}??ToVW_;Y*aZ_LzED>u)4Ka);sud}YMj4qv8KP(=wgxe#Vf0ev zx^6SiBTzVk-cH((6INg0Ss#k7ActI3{#&17bwYRkpL7b}I0PFZX`yEIG}&BKuflCC8?oy;`TEcblpq8wXyGnu zkQ<7y#NpgIL(-(8_akN|A||OwauCWuNTQH9R9a}(B#4bvTj@zF|F<%MX|KTQH8@>lB(8Y9hgL8mp0)%UXiwW+4IEB%O zfaveEu4XI9ON0nMebkqu(MU<_I;@Avr(Ss$cHs6-NtLD6^mv@UFo4Iw~ zCR%SfhKa)lj?ue!;8|ZMz%4}~rk*G0c^y!+Oqy9z5(Z_Stf#cMU zPJTY>*T-|@=+iY%kE3>j+Q!@OhPxI^=jD@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/7d2570a230d731b54e04320f4bce5693d5bd4176 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/7d2570a230d731b54e04320f4bce5693d5bd4176 new file mode 100644 index 0000000000000000000000000000000000000000..8121744eb8f3c432d167ebcdd91d46e8e6b7b105 GIT binary patch literal 9828 zcmeHNTT>b_6z&h{L;Kd3I=Nro3cGHL_D;pNFK5^bEw!SfmQvfl?o3ZWaEXYkGKfqv z%#bWO*)QMul5?_)eyX*#OfzCNv7BPzlo`B0siB4wAq6E=DkjMwwrLUPdECiuk*G*Y ziQOe-XdyM)kfD(@T$IeJ^&(0V&6pID3PKgdn+ndjq+CfV8R3dC92I}6INm(44+-mX zh#iqSbTk=6n>I~T5od9vYMULCcj{S`itLHXk}iQizaj;rLIDicA^__?Eo|x5zvs_P zjF))}e==`CD`20oX5csMKpz+Yfmd<=+xLF271z_O6%NTYDp}F|?D5~T zGrFDPM5oK}W>gc(grZy&LZRBPEX7{Y>mBWP4|;Nh677mcuXAv;-#&3yQNVM{&`RMj zC6lWST<@yTn#IYd0|)QK!SIS>bTY4T&vV?)l??-1A2WagJi~Hxnkso6SKe)^(=+kL z?QT(q>~@Qb@&G4r0p8VCYXY8wS5-$CrTE>Iw91Zf*gR*9R@*e_aw{n5CL8twcciit zR&7B$Y(Yo2+$^dD{(I0-g$#Xt68q&O%L_V%EC(zuX?Lh|N4PneJ;3fU?7cmOgRPf> zK6*q3S)6as4U|SInqPp`ca_*yJJ8H~1Nb3c_b}QQnBz-M=sp|+d|=I=r_ca61g0(Y zMVD+s-yXB3Ri_%h!lAV9cbX6%0vtiM8)24;XUFT$k4~M-q00Gnn8d(3roticxYN;% z&uZ1SY%glAYAPHO;ptU?t&j+ZMEH^@+y!q*hXd6NmS%FaqKWVf_*XbNOkl#5=im_6 zCd^D%Jf805S?4sOyT-NQqwJ6kPm_AyT0d`BeRC1A;mhw}^5Zn-vu;kPD zJ-=o4?@#ZxyYE8?r5DY+2|Ub;%FBlQ>#*=CZ)`eE(0OYi->8D(^@k(zVyKd!)#l!uN2xK zf6cM8%0;lTfeISNyl`n%fXYgkWHwEG>moA^wnTOEdt~avdqgd%xdMomLF}9=H zXOM}=Q@FX7Cz;JABGn6~J9tL*!E13j#5hg&<{|$FwAWiEbk0KDm89C>#2D(We<$(x VPL-Aa>>{ah)9(iB_Npz>egN2yxbOe~ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/8e78a58162034efce763c158087c6f1e427c1260 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/8e78a58162034efce763c158087c6f1e427c1260 new file mode 100644 index 0000000..53c76fd --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/8e78a58162034efce763c158087c6f1e427c1260 @@ -0,0 +1 @@ +55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_13.json b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9150349979ceed8b2f6db6e0ed836462cd27d499-1 similarity index 81% rename from vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_13.json rename to vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9150349979ceed8b2f6db6e0ed836462cd27d499-1 index 9f9dace..eb0011d 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_13.json +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9150349979ceed8b2f6db6e0ed836462cd27d499-1 @@ -1 +1 @@ -"example.com" \ No newline at end of file +188281282812-00b \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/91a9bc8bbcab0dc05bedaf5f4aa8d383c1651fb2-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/91a9bc8bbcab0dc05bedaf5f4aa8d383c1651fb2-5 new file mode 100644 index 0000000000000000000000000000000000000000..74209f175fbe041cce34c2f14f6cb2fcbe6bb15d GIT binary patch literal 60 zcmXxV(FuT13AkqiVk3ZyZbsY$ZZT3uVe*WTFd zboTE#b%eByQE?oBwSJn`!YJ|rl2}U;S*`ITNFWGV63{5E5DJo0A%RHFxRClxXTmV8 zwF1hOA(Ttu?nX!@Ij2M$p(u#TB-89POlqk);T)V0!Ua`IyNOf~0hY9bDhaBAiA>@Y z27y*-WNK9}WMLp_;D@nxb11hg1Rs2>{WGo3iTj-noQ=fb)e{ejI8+iCw_Fk!oU_%h z+tn+}cWh(2kuI++g{uq8jjf0IRsq6!UTSuv01a7j{p|vTZwtQollccskM5e*ICD8h zwAhckuh+kbKdR`yH=yRHhl^XqZ&hS5%WOyN!Ugo6s0a%04E^9DdmhZmy@LcK?#$TIxz0hi1Ky?&;w4&N-0W&~a+Se# zzCfmM-Lz=k$W4XUuqn*N**f}7bYS9n&wWfd+K)#4-v`Esj2xNay$T8c$2!|tDszq3 zrqBg8urX}!YcrcpGppQc4wYV3M_UH^)f#H3Uk~&5l1F8goo9s`DS5R0v$ZlG<*8Ki zsN_+e6>g-6ooA@v-e3{Ziwoy2q<dea7|FxjZY( dv3tDIUdf}}Sz*p&-GKo+?Z|JueqcMuqaRj$^3(tT literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b new file mode 100644 index 0000000000000000000000000000000000000000..498e5b9a81a306711fa89b6bf0b8e5e660d024ee GIT binary patch literal 837 zcmeH_%}T^j3`YAX^8yY@ZgPLN({?~~p_F0J&4=S{LD5F@;E9lhT91BN`Wc-Q+Gzz8^V#Gg0=k1~8*aSJRca9s3_dR)?3hUBjS&sZ!y90qg? z@Qv4F`!yRIb188w7NP_a=ExR{qM9zyD6t}@7ubyx+$vGt>pd7{ytMxvOjt~y1oDa literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9355e3410f2f344ecd5dd798819020a35461c2df-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9355e3410f2f344ecd5dd798819020a35461c2df-2 new file mode 100644 index 0000000..49da538 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9355e3410f2f344ecd5dd798819020a35461c2df-2 @@ -0,0 +1 @@ +c|u| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9544d0384139d241f81c841cb63f4a6bf2c3d55e-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9544d0384139d241f81c841cb63f4a6bf2c3d55e-4 new file mode 100644 index 0000000000000000000000000000000000000000..f74237f441391545454dcf34dee162a0d1937cc5 GIT binary patch literal 33 ocmY!|G&DA|Ftac=H#aggGfZJ%U~n+DG&Z-iurRVPG%{rX0BW5EA^-pY literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9802e09660b74c259960141c89402b5fdececf3f b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9802e09660b74c259960141c89402b5fdececf3f new file mode 100644 index 0000000000000000000000000000000000000000..f205de9a076aaecd41f5baabac0681c35e5c3bd8 GIT binary patch literal 55 zcmWl`(G`F&2m?TV*@6jt4Y48J$Ngte@3Jzp{smB$InxlHh~eQJyN%xQ(db&uoACnV CeF&TY literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/98840eab4f9516cedcdcc88302b3639672a42f06-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/98840eab4f9516cedcdcc88302b3639672a42f06-2 new file mode 100644 index 0000000..d14c1ae --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/98840eab4f9516cedcdcc88302b3639672a42f06-2 @@ -0,0 +1 @@ +5555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a71d9b48c814eb1b0db3133482c06a079de2bc8-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a71d9b48c814eb1b0db3133482c06a079de2bc8-4 new file mode 100644 index 0000000..75f22e3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a71d9b48c814eb1b0db3133482c06a079de2bc8-4 @@ -0,0 +1 @@ +8673617379884547205962240695953369140625c|n|name flag fieldu \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a86f34bfd765bab80845da7128ab574d6abdef1-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a86f34bfd765bab80845da7128ab574d6abdef1-5 new file mode 100644 index 0000000..2895213 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9a86f34bfd765bab80845da7128ab574d6abdef1-5 @@ -0,0 +1 @@ +i/o timeout|pW272204682680184470K[Cu| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9cd2374f626d4c55ce9389368b428a74be518319 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9cd2374f626d4c55ce9389368b428a74be518319 new file mode 100644 index 0000000..3ff4e47 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9cd2374f626d4c55ce9389368b428a74be518319 @@ -0,0 +1 @@ +____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9d52d6b15a5ee8cd7a575bac4dec1025573ad062-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9d52d6b15a5ee8cd7a575bac4dec1025573ad062-2 new file mode 100644 index 0000000..73a4ac4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9d52d6b15a5ee8cd7a575bac4dec1025573ad062-2 @@ -0,0 +1 @@ +01234567u89abfdec \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9e6953ce446955eed1bee2d9819461068d2d37f6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9e6953ce446955eed1bee2d9819461068d2d37f6 new file mode 100644 index 0000000..a1b2e0f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/9e6953ce446955eed1bee2d9819461068d2d37f6 @@ -0,0 +1 @@ +5555555555555555555555555555555555555555555555555555555555555555554555555555555555555555555555555555555555555555555555555555555555555 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a0704a231fa435579a323a222d91a03fe3b5cbc2-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a0704a231fa435579a323a222d91a03fe3b5cbc2-6 new file mode 100644 index 0000000000000000000000000000000000000000..c06a6c889c1e21df7d10595bdb007f8ad6a5abab GIT binary patch literal 53 wcmWN`!4ZG}2m?Xvh=U=4{tHw0yWBML(rTY~(|MS>K}tq7|Lq%LKT(LN4=B$Hq5uE@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a1f084b3911d33e6b41f2ba29efbf9140800444e-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a1f084b3911d33e6b41f2ba29efbf9140800444e-3 new file mode 100644 index 0000000..1b1bb74 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a1f084b3911d33e6b41f2ba29efbf9140800444e-3 @@ -0,0 +1 @@ +5551115455625 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a3953bd6a594600ab51268955ecee6fea8be4709-8 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a3953bd6a594600ab51268955ecee6fea8be4709-8 new file mode 100644 index 0000000000000000000000000000000000000000..a6decd14647df88316fab62e0fd6db2f4da89ed6 GIT binary patch literal 8 NcmZSNU}OLSUH|}F02lxO literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 new file mode 100644 index 0000000..889de47 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a61e7f9a73cdb1f8e21d1cc341429f15e1db3172-1 @@ -0,0 +1 @@ +5555555555555555555555555555554045555555555555555015555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a8e6fe772a578fe63546761ea1c195ff61203810-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/a8e6fe772a578fe63546761ea1c195ff61203810-4 new file mode 100644 index 0000000000000000000000000000000000000000..9379793e673be0e5b272f406c771a38620bfcbd5 GIT binary patch literal 13 Vcmeyx!0_vIY5o8I|9R%r001?R2h{)o literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/aed10bc423e56534538d83702d4be2aa281549a9-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/aed10bc423e56534538d83702d4be2aa281549a9-4 new file mode 100644 index 0000000..fda02ee --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/aed10bc423e56534538d83702d4be2aa281549a9-4 @@ -0,0 +1 @@ +555545555 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b13d2b8e3724d1787d2105c1a4e3220e1e690339-1 new file mode 100644 index 0000000000000000000000000000000000000000..290d77bfd901b4cc5d0da96f97ca74369b2a6d96 GIT binary patch literal 89 zcmWNJ(Gh@92*Vh~1@u~=YWU9r+ R>P>WIX&<5z<;>oijvoyC5nTWP literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 new file mode 100644 index 0000000..08df4b6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1dc3183c3a0c093dd7b36bb8ef2a01c20e45635-4 @@ -0,0 +1 @@ +55555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b1f5380ef7c0a96f102e2ac2fed5e4a227a0d9f4 new file mode 100644 index 0000000000000000000000000000000000000000..bef0926e4204f9c4ab45c0cfb5e1b1313ebc386b GIT binary patch literal 42 kcmY!|G&DA|Ftac=H#aggGfY9_GUyswm>3xwSr{__0J*dXZ2$lO literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b22334c4d7507820a3b901dcba18b20a74b28f22-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b22334c4d7507820a3b901dcba18b20a74b28f22-7 new file mode 100644 index 0000000000000000000000000000000000000000..1d3f9d707f005604a25911e544766fb1a5dfd353 GIT binary patch literal 6 Ncmd;LU|?Wm1^@s@01p5F literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 new file mode 100644 index 0000000..578df8c --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b4b2324b290ec96791a1ad910fd62d8b6d5b32cc-1 @@ -0,0 +1 @@ +5555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b60c99af5868c013f98cdce9781b4fffeed81f30 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b60c99af5868c013f98cdce9781b4fffeed81f30 new file mode 100644 index 0000000..d7ccd0b --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b60c99af5868c013f98cdce9781b4fffeed81f30 @@ -0,0 +1 @@ +____I_Rc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformatin5545____I_Rc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformati \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 new file mode 100644 index 0000000..3beb581 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 @@ -0,0 +1 @@ +c|W 0^&554827056640123456789abcdghijklmnpq828V12-0rstuvwxyz]=!(BADPREC)68@'E>103ĉs){1Kb55555555555555555404521701246134e460155555555555555555555555555SetTokenInformation5555555555555555555555555555404521701246134e460155555555555555555555555555SetTokenInformation554555555555555555555555555555555404521701246134e460155555555555555555555555555SetTokenInformation5555555555555555555555555555404521701246134e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555655555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation554555555555555555555555555555555404521701246551354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e46015555555555555555555555SetTokenInforma____I8_JRc__e_5555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation5545555555555555555555555555555554045217012461354e460155555555555555555555555555SetTokenInformation55555555555555555555555555554045217012461354e460155 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b7b180de011becb75b415d308134a35b1c3e075f-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b7b180de011becb75b415d308134a35b1c3e075f-1 new file mode 100644 index 0000000..425f1bb --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/b7b180de011becb75b415d308134a35b1c3e075f-1 @@ -0,0 +1 @@ +c|u|l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/bdd90d98c50056c82fa01cdee2d91ef30112c4d7-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/bdd90d98c50056c82fa01cdee2d91ef30112c4d7-1 new file mode 100644 index 0000000..ae33c1e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/bdd90d98c50056c82fa01cdee2d91ef30112c4d7-1 @@ -0,0 +1 @@ +M5555555555555555555555555555555|n|ne \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 new file mode 100644 index 0000000..6c9c10f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 @@ -0,0 +1 @@ +||34651953614188823848962783813 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c372591e0c943653714cdc9b1e52f6b0a49a0ab6-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c372591e0c943653714cdc9b1e52f6b0a49a0ab6-3 new file mode 100644 index 0000000000000000000000000000000000000000..07072e39af344f5531bf9e910d54ba5d21341c28 GIT binary patch literal 32 ncmeyxU}j`tZed_x@#}PH{ePafL0K(oT>}3tEEAK`Qc@cM)0z!7 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 new file mode 100644 index 0000000000000000000000000000000000000000..4b12f9d32723acb77d2f300d2f812c917180c68e GIT binary patch literal 78 zcmY!|G&DA|Ftac=H#aggGfZJnKo?+OFgLa|Hn+5}FtRW-GDYL+8dM~v8dRjYBpI7K GB>@0h_7IK$ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 new file mode 100644 index 0000000000000000000000000000000000000000..72996c8c25f003845bf8db1d700e0ff3830ba276 GIT binary patch literal 52 zcmWN@K@k8T3+TW^9(09$Rs*wV65-H4cq4!K5dbgo)Wc`K6T~IS;Vkg@ol7paa SM#1>#dqi{&lPbLtp4SH>7!lL} literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c775292f392c027f7d24e5a1c84b1dd176c03f32 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c775292f392c027f7d24e5a1c84b1dd176c03f32 new file mode 100644 index 0000000..f7217c9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/c775292f392c027f7d24e5a1c84b1dd176c03f32 @@ -0,0 +1 @@ +01555554555555555555555555555555555554045555555555555555015555555555555555555555555555554555555555555555555555555540455555555555555550155555555555555555555555555555455555555555555555555555555555540455555555555555550155555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ca269332cbd02cb17415e5cfc4ef7403875ef755-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ca269332cbd02cb17415e5cfc4ef7403875ef755-5 new file mode 100644 index 0000000..d8ea44d --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ca269332cbd02cb17415e5cfc4ef7403875ef755-5 @@ -0,0 +1 @@ +c|أB551X \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/cedd771f15bd51b21b91d2535588e6bfd943456e b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/cedd771f15bd51b21b91d2535588e6bfd943456e new file mode 100644 index 0000000000000000000000000000000000000000..fef1b680bd13350f562c7e8edf2ff68ac89b952f GIT binary patch literal 16658 zcmeHPOK;Oa5U#`xapS@PA-Hj&+S&IWkZ9t%qPz)hp$A5B;y`Je1X@Zc@Y5}^aqC7| z5-U`0QO)?W9%sFeZ@!s*%sSbf8(Eg!djBh9Ml+LTEcy8Py3xXD=d3W<&1(Xp@=?e-d-W+FRxbqDcK$MR_B zE$)55Roode{Qgz-n_3~J2v66C+xQp}HW&iFL%ZL=FNjUl5*?!Zw%$uOhR8S3qIvO5 zZZ7>4o{-iPTQLEQ3A6lwjT+1MJ=qf3dWXERrR5X7fvs+TgrDToK8|Zbp#+0{JV1QK zTYJajN`1M;;gQ^7t9axNc+2TygWEV%?&U@cqapgXbheso04Fkpa(swK0X~IDJSrb_0(^)^1#yBjz=`}(IX=Xr0G~pv zACK}0YOZgZ4HsH2()ww;+Vx0)4|$D(I6)fVM59kRKE$H{pF$)a(QLTj!colN1SxQ*bsl!cVdcp+O`=ka#xDgp)nM59FPG(hs4bt) z&(-yWIpG~Ki6+7!CvthF&zPAre@Hwc9?fJ&Wjvx~Mt;i8gS-e5|LYMj#H|C|eSVCC z^)(4gOS6w}UFed9PH)Y01g8(H7%1kKUq$JEwY)mt-219@AaLGwUSLhDgm^^LnQ2Cx zN`Xb3ETw1W%pVeuh(|NoK|K1G=fVT@XD%=I$uhH=W)Jl^$3HZ4(Co1^AHH z2=FPy04L&60nBL{;6pqL@F~OqC*n~74DpCQGOX|`$-vIY9|d++hyhMD@JGI9iv$zO QzE!6KQT|^Erv3!rH^tKQ;Q#;t literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d22b7d7f10d50e7cd68cfb65ac60ce2af5e05f0a-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d22b7d7f10d50e7cd68cfb65ac60ce2af5e05f0a-5 new file mode 100644 index 0000000000000000000000000000000000000000..d93676d56d8d58af07ddf560b72c955fe1dcfd48 GIT binary patch literal 12 Ucmeyx@auGG{r~^}dFIpr05p{c)c^nh literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d24d432b5104847324add3b047f71cfbb2cf11a2-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d24d432b5104847324add3b047f71cfbb2cf11a2-5 new file mode 100644 index 0000000..ddca4f9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d24d432b5104847324add3b047f71cfbb2cf11a2-5 @@ -0,0 +1 @@ +f|p GtCorNamA+eExW-809244u \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d2a3b921d428c6ef1dc976623d0fd3914b8b5924-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d2a3b921d428c6ef1dc976623d0fd3914b8b5924-7 new file mode 100644 index 0000000..ba5d70a --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d2a3b921d428c6ef1dc976623d0fd3914b8b5924-7 @@ -0,0 +1 @@ +c|pW s%!(BADPREC)568170319boo�lu \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d5c5747ded386a1de2be97f8fa56f27dbf866331-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d5c5747ded386a1de2be97f8fa56f27dbf866331-3 new file mode 100644 index 0000000..08e5ae3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d5c5747ded386a1de2be97f8fa56f27dbf866331-3 @@ -0,0 +1 @@ +yoverflow on character value \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d68e96f1fdefcc1ca114970b7d9ef1cbd5a0cc50-10 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d68e96f1fdefcc1ca114970b7d9ef1cbd5a0cc50-10 new file mode 100644 index 0000000..044fc13 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d68e96f1fdefcc1ca114970b7d9ef1cbd5a0cc50-10 @@ -0,0 +1 @@ +|W 7%B5S012349acdefghijklmnpqrstuvwxyz]=!(BADPREC)8@'E>1031Kboo�l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d9af7dc7888daf056627088aef8cfadd5817660c-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/d9af7dc7888daf056627088aef8cfadd5817660c-6 new file mode 100644 index 0000000000000000000000000000000000000000..421673d65347cbfbcb7a58c229cfc24e1ec21ef7 GIT binary patch literal 7 OcmZQjU|?WiWCQ>J$^at( literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 new file mode 100644 index 0000000..e69de29 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 new file mode 100644 index 0000000000000000000000000000000000000000..2a7c944e26efe4bc1cf32dd3fbdbfc4462c51936 GIT binary patch literal 10 NcmZQz00IRN0RRB103iSX literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 new file mode 100644 index 0000000..e42b800 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 @@ -0,0 +1 @@ +<557555555559 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de7d905f4388e2955b0a11f42517882f0ff5792b-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de7d905f4388e2955b0a11f42517882f0ff5792b-2 new file mode 100644 index 0000000..5bba876 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/de7d905f4388e2955b0a11f42517882f0ff5792b-2 @@ -0,0 +1 @@ +|u|l \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 new file mode 100644 index 0000000000000000000000000000000000000000..05a2d49b27ac0e1187cf2f37200f10481671facb GIT binary patch literal 5 McmZQzWME(d000XB1ONa4 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 new file mode 100644 index 0000000..47d9faf --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 @@ -0,0 +1 @@ +55555555555555555555555555554045555555555555555015555555555555555555Sz_x_q_5 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e3b22b4eb898b68dde1c73dab4629c38025031db-5 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e3b22b4eb898b68dde1c73dab4629c38025031db-5 new file mode 100644 index 0000000..051fbb7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e3b22b4eb898b68dde1c73dab4629c38025031db-5 @@ -0,0 +1 @@ +c|pW s')0567383170319432u| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e55f990e122023ab58626ef27e06422b7c4be053 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e55f990e122023ab58626ef27e06422b7c4be053 new file mode 100644 index 0000000000000000000000000000000000000000..d0bba70de7bd48da32911d07cfa9084e22389693 GIT binary patch literal 260 zcmWO1%}#?r6hL8izJsg2K+U}jFzCt|W~QMM8?{#3&CM`B4Vs_@+cZ4Atk32{|9+&O&tIL literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e77d34eb148eb0a3b30feffc7e9b56cd182dc74c b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e77d34eb148eb0a3b30feffc7e9b56cd182dc74c new file mode 100644 index 0000000..309beb4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/e77d34eb148eb0a3b30feffc7e9b56cd182dc74c @@ -0,0 +1 @@ +5555555555555etProcessMemoryInfo5217012461354e460155555555555555555555555555555545555555555555etProcessMemoryInfo5217012461354e460155555555555555555555555555555545555555555555etProcessMemoryInfo5217012461354e460155555555555555555555555555555545555555555555etProcessMemoryInfo5217012461354e460155555555555555555555555555555545555555555555etProcessMemoryInfo5217012461354e4601555555555555555555555555555555 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 new file mode 100644 index 0000000000000000000000000000000000000000..c110ac8631b562ead348540ae37cf067a40aec35 GIT binary patch literal 8 PcmZQzU}RumWMl*Y02BZP literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f52fb64e8823fdebdb11ae1c231358fcce57e638-6 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f52fb64e8823fdebdb11ae1c231358fcce57e638-6 new file mode 100644 index 0000000..b180e5c --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f52fb64e8823fdebdb11ae1c231358fcce57e638-6 @@ -0,0 +1 @@ +c|pW s%!(BADPREC)56383170319boo�lu \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 new file mode 100644 index 0000000000000000000000000000000000000000..671ee03a0cbc982a354f0e13fb51c80e9062744a GIT binary patch literal 262 zcmWO1%T9za6o6rNzJn`YV9Yr!L(!Ejr6c2HOuP@9lhO-86BNb^vhvYo{cpbiY@!W~ z#A-v=fI_feA_9u(u>IM$Lf&06(^b literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f748f012d8d9bd2b168aa96c529658761dd648a4-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f748f012d8d9bd2b168aa96c529658761dd648a4-1 new file mode 100644 index 0000000..0a92386 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f748f012d8d9bd2b168aa96c529658761dd648a4-1 @@ -0,0 +1 @@ +515111512312578270211815834045410156250xD95782702118158340454101562555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABbeDddDfd9eF6C55511151231257827021181583404� 54101562555511151231257827021181583404541015625065072254514016141043235136515203622404016.0xfCE3BdA64ABf82208f6CDcE92fbE6 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f8f96538c274d717ccca38324c9aa658e67180dd-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/f8f96538c274d717ccca38324c9aa658e67180dd-1 new file mode 100644 index 0000000000000000000000000000000000000000..1cf2d97575042ad65423f9792af58db5aa204273 GIT binary patch literal 128 zcmV~$Jr2S!3gP3FPo?(aCCn>Ir;f9v{bSc<2;EQ{| P`BWmZ=+Qi9$t;Qf-W(&? literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 new file mode 100644 index 0000000000000000000000000000000000000000..cc2715c20a722c2c06f74e0e37262465d8f18a4f GIT binary patch literal 248 zcmWO1&2oY;7)Ie-3OAthB{3v)RX`A>m9ch;xOsn$JY>aLQI5pCi&`z0=brdu#GR(yh2ZfNc)PAJjCfMmYJ0;R zx>ew6_OmT$59~0ft}@5|Rr(L~Zc8iLtOa!cg)E0>)8rz|M}VF}gBvvNRv`yr*ng&s JJ(HY{WB)Z5Np1iD literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fb51f26fe62e769ba34f569454121f46f2a4d277-8 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fb51f26fe62e769ba34f569454121f46f2a4d277-8 new file mode 100644 index 0000000..9f1ef19 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fb51f26fe62e769ba34f569454121f46f2a4d277-8 @@ -0,0 +1 @@ +f|W s't)05678too few operands for format '%19432u2 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fca6bc86ec8711a1e7745c03237087d55d936a67 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fca6bc86ec8711a1e7745c03237087d55d936a67 new file mode 100644 index 0000000..7de821d --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fca6bc86ec8711a1e7745c03237087d55d936a67 @@ -0,0 +1 @@ +55555555555555555555555555555540455555555555555550155555555555555555555555555555545555555555555555555555555555554045555555555555555015555555555555555555555555555554 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fd155cfb10f96df4544263f5d2164351ae97f806-4 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fd155cfb10f96df4544263f5d2164351ae97f806-4 new file mode 100644 index 0000000000000000000000000000000000000000..8661a0a620a9176c1b6fbfabf0629059a09fa98e GIT binary patch literal 44 ucmV~$0Rg};3<5CbsL-!aB{y*Y8lDu@&pQs;lL_ntarmhU?rkrkP!~VF`3M&P literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fe5567e8d769550852182cdf69d74bb16dff8e29-1 b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fe5567e8d769550852182cdf69d74bb16dff8e29-1 new file mode 100644 index 0000000..454f6b3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/compress/corpus/fe5567e8d769550852182cdf69d74bb16dff8e29-1 @@ -0,0 +1 @@ +0123456789abcdef \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/001e59af3c698337b5449d856ef447fd0c0b47ff new file mode 100644 index 0000000000000000000000000000000000000000..f39e43d33e64cc3e6b6717486ab31ba57582545d GIT binary patch literal 4211 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 F`a9OCM~?si literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/03648029374f39fc083b90d39df1f80ecc1fa78e-1 new file mode 100644 index 0000000000000000000000000000000000000000..75ee5ed48cfd926b8b8b04d1502c4c5971efb2d4 GIT binary patch literal 56 zcmV-80LT9k{Qr*-%n%$AD1s(*kRU0TVB#Bz|Nn8Z9LYd_X8`~vtORo-cw@DiUx|Oj Og6MdL?-}<+8{r16*BI&m literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/057294475853d7ff15d86d889f592eb7ba6b2e72-8 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/057294475853d7ff15d86d889f592eb7ba6b2e72-8 new file mode 100644 index 0000000000000000000000000000000000000000..853c9ec0629f184df461aef601a20a28df36beb0 GIT binary patch literal 4 Lcmexg&%gix1$_a3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/067422cb1d02d21c8fc4d86a4b00c126d3f24699-2 new file mode 100644 index 0000000000000000000000000000000000000000..84f9fbd218f407509a0d9809384613ba14587a39 GIT binary patch literal 171 zcmV;c095}J;2jX)|NnPD05rPzfWR<`AXX7PNs^p2!vDWzsM7r3^8f$;|Nkwl|NsBL z1A)Q^bgJlrY2W|!zvC^eI4raA#XM&(1|2*OMHj+8T#f($ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 new file mode 100644 index 0000000..9997a24 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0c33deff4510591c4ec94593a4d13f9d899523e4-5 @@ -0,0 +1 @@ +oG5 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0d67d398462565f4d9e21f5efe9b0a6816e8962c-3 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0d67d398462565f4d9e21f5efe9b0a6816e8962c-3 new file mode 100644 index 0000000000000000000000000000000000000000..cbbe7d8c4d79899589e4843a3918c9d72c6f795d GIT binary patch literal 49 zcmWf6AS>|T|Nrd{3?_#@H0*HbRJbN!<2h-L(V_qQlUFSIR6q4U2;?vP3nWcL@?Qb~ Dp~fBJ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/0ead65857937e78706dcaf139c616ef71533b94d-2 new file mode 100644 index 0000000000000000000000000000000000000000..c928bb1937010bc2b773196a072d94eafda252e2 GIT binary patch literal 169 zcmV;a09OAL;2jX)|Npl@05rnzfVe=3Al48(Ns^p0!vDWxsG{z&EXHz7xrB*lS XM~Hnvc;umoz5#6tiOWd8r7VbK2ps&B*486WZ8!^GV|uByy{0>`=| R6)T1wKxgq*DE+74SpJ+d9~J-r literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 new file mode 100644 index 0000000..fc5c08f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/1fd68df0abe0dea0a5cf30153dcf48b5684a77de-1 @@ -0,0 +1 @@ +g| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26157894111c075cd978a0a67a1bd2c6184e92d6-3 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26157894111c075cd978a0a67a1bd2c6184e92d6-3 new file mode 100644 index 0000000000000000000000000000000000000000..0d77c1bbcd0eb6c1dfedb64e1f1e7359449ead46 GIT binary patch literal 32 ocmZo{`Tsw?<$oq0S5NbnzyJTg_t<{Q>FGw7w+zQjlH`&Z0YZ8a%m4rY literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/26cc3dcead75312b7037f0c81d2a88ea04cf2c48 new file mode 100644 index 0000000000000000000000000000000000000000..4df3ef1b91e2bdecf4016bed0864b801d43b3791 GIT binary patch literal 554 zcmV+_0@eKk5b*#100jI31jN8_C^XoRVgP_(0RRAk0Du4h000000EQs|0001lVFCgO zfCc~p3@{9WfQAS{0+kvSQIT6La1AAM3XE(ZSFC7Tv|gMni1=FkS+2+}sNcc|e&81> z;wWetQ8f5b(Bh`y(t2^SAmVHBXSpJ`pneM<_<>)jh@+roMA6_!L5rJ)OY6nSf{3rh zpXG|&g8EI_eE9MB(hLF(hd&J*ek}FIdi0_a1KW+h6P0dIrw#Jw>a9bn6VQM5pTqz7zpRLCc7u!HHqit<--YCemyGJNn!l|i|_va0i|C13IG5A literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/31a1eb16673086976295a4042ccef7fa443503df-11 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/31a1eb16673086976295a4042ccef7fa443503df-11 new file mode 100644 index 0000000000000000000000000000000000000000..6a1d007f825640444f58ef32c3cd536399fd005e GIT binary patch literal 5 McmeZdU}0bZ00DvkQUCw| literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/326998db244ec22e4545688efc3fcf761edcfa47 new file mode 100644 index 0000000000000000000000000000000000000000..6993da704d811791f07e76aa1a15c50fd0856a61 GIT binary patch literal 58 zcmV-A0LA|?1S13r;s5_n5CKCm#uQ^#IpzQVN3pQ~8&*>(52yq_6KIY^FnB38cemFy Q06PDk$1JXNV>U5>Af(tAIsgCw literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 new file mode 100644 index 0000000..0b8c805 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/32796a5dc0d50e6c16a3400af331c4a1788d2620-4 @@ -0,0 +1 @@ +\ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/327ed0588eb0b927e81d9b9adfd8aa98a1a5081d-10 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/327ed0588eb0b927e81d9b9adfd8aa98a1a5081d-10 new file mode 100644 index 0000000..f32f69a --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/327ed0588eb0b927e81d9b9adfd8aa98a1a5081d-10 @@ -0,0 +1 @@ +)$$ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 new file mode 100644 index 0000000..d0ba7d6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/33844260640d4b3bc276376be9b5b5a1c53350cb-8 @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 new file mode 100644 index 0000000..acd8acb --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3b3dc5be03fd492a33bd331979fb5498f5df1e52-1 @@ -0,0 +1 @@ +%ḒoGhK5h2JSZܼi,Gsy;8s! \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3d648fdd4eee536b735033f7eb135b28ca5c8526 new file mode 100644 index 0000000000000000000000000000000000000000..13471a03c9ee03b3aca5e016f06ebbc4115030fd GIT binary patch literal 127 zcmV-_0D%7!@c;k+BM<;ajK@JyJ&9AoLr5`&;{RU~qwD_;8^p2eWs~m0%1AK{)^b literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 new file mode 100644 index 0000000..d87b4e2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3da89ee273be13437e7ecf760f3fbd4dc0e8d1fe-7 @@ -0,0 +1 @@ +) \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/3e9b93aed9d65aab72e65351b433bce4a091ab0d new file mode 100644 index 0000000000000000000000000000000000000000..3d0765d8514e826c2a051e7f6908c5c2042f7d24 GIT binary patch literal 372 zcmV-)0gL`K5b*#12n75J00Lx)TpAA(vnWHb08t1BP=Ejc00aOC2oM4Q006?I02$*H z0e}nw1|SBIb?vfGi1~q0$O65k<1GPQo~4W~tXIffnd}6GC|yjCbJ<%Oj_Tbr;qc1u z^Ef-#Wt`Gc-1ap_m!2AY2)bK{>M5$Q$-#_i*EXw|&QnOP0&Z8H|0kCp7*(-UZ`~y^ z>_4@co5}1sB1?BuskckD`z!G{p80mAg?)Fse~^!Mk7ZQ10lnKhu?%}j^HU6po0DjA z@zmtCz{@O#qUFYUei z_f)3PRLlsBQuKxMnhUub&RXjAD{oauVQz#)a<}}oj=Lp|;t2OXV)NS}pDSu;jIYb4 zKaCvmc95-B3GVfCy{߼'0Qj \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 new file mode 100644 index 0000000..67409b6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/440ac3e84eb89ba7c864261c36567ec92f111be5 @@ -0,0 +1 @@ +G \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd new file mode 100644 index 0000000..5c2743e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4a0e9c56d9b4d655b8c750e01b63aaee512c79dd @@ -0,0 +1 @@ +5Asws7upΧ$ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 new file mode 100644 index 0000000..2a21c7e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4d92faede7356a8aa5c0fd7dc7df1cbf6ec7bc54-4 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/4f480dad3c4e936864adaa7707bac06e59272d96 new file mode 100644 index 0000000000000000000000000000000000000000..8e3f1c87f0999435ccb4ef6ccb1ae36be9914ff7 GIT binary patch literal 226 zcmV<803H8h5cvOp0D)fsAV7u4g(3Ms7R3k#2n2=#0D^!300;ztfFdvgBLF}cDl|YL zhyVfr0t#4KXbjk#|9N6?hXAje^##>gP@luS?+{%)se#&wTY0jX0Y2#4IG`GS#PSb` zJeNcc3&sT<2ZEhpEN?pr_{F!{DR=%DIR%Z%aa1d!=+>VUr{h3W7r@|$t_?dLb@;N5 zd#W0f>tvid4W0nqi>a^oF6oXPI}dNJw`UUtip1FwKJfg5X!dd6E{lSsQdi*sdjO7y ckU82t8BFk8TfvoLe`FjIt{INERWZH)0Yk4})Bpeg literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/500ce5edbda324f9a385f06a24094cee873bcf07-6 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/500ce5edbda324f9a385f06a24094cee873bcf07-6 new file mode 100644 index 0000000..7e1fe91 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/500ce5edbda324f9a385f06a24094cee873bcf07-6 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 new file mode 100644 index 0000000..71c7a01 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/5135c69c6aca6f4aad9cd65660398fc3a7bce387-5 @@ -0,0 +1 @@ +P \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/545816fc75823315f58483bdc08de39b4b26f487-6 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/545816fc75823315f58483bdc08de39b4b26f487-6 new file mode 100644 index 0000000..45e5287 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/545816fc75823315f58483bdc08de39b4b26f487-6 @@ -0,0 +1 @@ +t \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 new file mode 100644 index 0000000..4b539d3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/54d1f293ba75bf6ff72e8bf18fe15b00e590e2c8-1 @@ -0,0 +1 @@ +S" %'؎ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/555d303800fd439e509e0720e6d7cf04f744ec2f-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/555d303800fd439e509e0720e6d7cf04f744ec2f-2 new file mode 100644 index 0000000..f774831 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/555d303800fd439e509e0720e6d7cf04f744ec2f-2 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/55a0c930a804665fd0ae2aa914e39ec2898babaf-7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/55a0c930a804665fd0ae2aa914e39ec2898babaf-7 new file mode 100644 index 0000000..177989c --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/55a0c930a804665fd0ae2aa914e39ec2898babaf-7 @@ -0,0 +1 @@ +v$ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/56032dcc54f0d2fa736dd71962caa4e3e240abf0 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/56032dcc54f0d2fa736dd71962caa4e3e240abf0 new file mode 100644 index 0000000000000000000000000000000000000000..111b958427ea575377406b761560f929a496f489 GIT binary patch literal 1003 zcmWf6@c;jRai><+X1;^m%pCuoGc>Uq^gLkaG+=6IIKd&xC~WY-RZOm+D_(Q)Qv1#u!UOvH3Ho}zm zTIh}W^&%I~3UlAl_}_Q0a>u=fh@!Nxohhpf{#0H6BKzaV_rLG!Q|eRei;L8S?UhzP zy_o%I>)tz!>TN9|X5k-F7`Obj-X=Etl~*spd|}@jqz)NkGZUbJ|YBKWnYN zl8u=7XPuXdj7DAIqBrg$fuK59{TWJcfv+n z*8eA*J6@PALziM%$CTw_QUCj0JN@M8dgxJ=I(%51`+*C3{CzV3``9S4IC;>9ReIp9~v$wEKp4347?~inc3;VqsD8~ zGM=7@`79LHWL^8YcE8Zny>%=ipE<8iTUoizdAaVzQxkVSQ(ePS{_ENAI#sRezZ@FR zgjeYXe~xMQi(WKUx%jMi1m`=Jhk}B?cZZ$OFZ};H^@O~rP=6rHwcPkk@6N1x%lNG_ z*1*C}rMLV447Lr`1$>9TH#gpB={Wl((qB0F*_80e{wMLiZ|kG3e0d-+r{Vk6jVGQ+ z@^9JZqV4`{*7OZRcV5nZ|9k3+H(!+(%FZ%DFRc+1H2eCdlVs!^6k*Y~tc Weem!6`Tr}NjS2?dL6u)>i$;cLGUXG0gnlTEaKGm|NsBk|1-niEq?$2p*e$;cA^4X#kb@u)#5jUa5CkDm2oQvzAOc2U1V%uJFj*)gp-3P?LP1Ll zV_*WrTJGDzC;=eJX|w=1^Onho(N_X9Xhw^1OhZ6_AsF_k)22Y{h41Qkh~OP*pw8`F cDt_4HMDj-W=8~^|S literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6b93512fc409ba81e69a6c818c47540e47dcb9a4 new file mode 100644 index 0000000000000000000000000000000000000000..81f5c356f56cf6d0bfa0a4e8407682f78f3bb313 GIT binary patch literal 962 zcmV;z13ml$5b*#100jI45WqzW$5BZ&3sZy#fKh-5fdBwO00JWb0w4fD7!`m(kwicM z1O-sU0v!hOcm<$8073&$*2N)B78C@IE&k-ds?7N1L4Wq~ie@eO_2D8xt94=Lzz-w~ zjd}g&7EY(bDZv9>onpR+Bo`hC`k8k5xY)79n2}=n(ARnO&3&9z^+O&J%vUt?^H=DA zuH}Dw9C59pg6>DVLZ=HBp%?sTH5()(&%hj-xoa1q`oGl11(@hSKnhgVpk_f@RjQdj zkyj61C*Rg@_c15;YLiYDN6sNHt3y+wpe3%e6%9EDy39^#N{)^tqWlhu&MNXK+vL!Y zdYf{cmF7nPdtMpp&5@J{l5moA!wrdn1M{am+^ZS7EWjOZROv~tU;Md+)9G;Pc#11o zoW%&tMWF7yQU~;W*ieesSnsbc>hdWZIbShrOL#TAMH$8NsN{WlaU?cpy)Pg17=mPX8J^4J$RjbTkpqR$>J=wiq)~EFbzhufDmDv#Nf`BZB#gW`6z( z9niJ>Z;vCcRaDUZXjkZT!6Nj6|Ey+%gyb2RLsvQn8A8DVo3fhd@b~|J7TQ(Gb4n{| zxF66(3BlQYx8S1uMIToiy}zHB*pG|yCt7vapYDIi;i{@X7xZ`qpg#aY15nn*Ax#z( z1dc8KM+k%K5`iR)}dL(YLNvs0RqqhpCEzk{N)iag3T zIW(l+rd(&G`4PaLSB83XBqf3*oFv_FLt@~-{3#FjYKATgaEBXJdeZ9`e{SJ)I-EM5 z;z|~0F#>ZDs5`IJ0X-i!l;Snk`>Tt(d$aG^6ok)x{ca^S=FnVK9N@sUMJty`*ByYIExXOi$L9Zr4H!%u%Q&MvEE-@)a6q+ za-frbtBgl0eY5cQCziY;9vz3WE-I+8pd)Z>@h1mXWyUWL`m>K$G;7JP4;KkqtqVH` zejr(B%H&$P?O#f~k;j1xFfcSQ z2=HxwBFksa7~r6OBPRWN&8}zHj~_qMdb!lkPu`VLVWy_e^}xWgy~}^|1;a+Yx6}Pj$F=((EtvLYVcd@0bH2xD ztk2N>=q=-_u{60b-E?oOx61_E$a8kP|2ZTv#op4NJ8iGshyHu(_ZozW*fDHhI>p>| z<`oNNk%T>*p_T4;x2^kmcHRu`xo);B^B?{7va0V~xhec~+R1dcS&p*jMKfgzZvF~$-U{cofoT+OvmR}2QId-^(W#?Ss*w%83X-XQB zcMH$u%w3wqH1)xeExXHh7*;O)DR+FQv2o=E?frK@w(~i){<#@>v*^yk7yJCZ)x)Gu zR!8(-Ue%OvK|&z2^!4d?ziW^04i>mgplV_GcAadVPh7^n6AKA|_>X?(Di8 zy2rfOkY#SV&gTPeky>g2oPIvLv)iR7i_dyrc(5+@o$S?s9n05j@_xYHbI91y+m7x2 zA*u!7!I#%B@@Y1wXHS_dzw3fa`;7+go_6D>ef_SEyVN@STb6HsU%l&NQQ8tY5zYD) zzaL#+;_-0v8p-4XrmU_z{Y_rzs()m$zp=h(zsZqDoYT3B_lMW$z2jh5;B_&q-hGDQ Hg#U~Hdq!(` literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ce2e7227237a64b8bc0b5c27f018bfd2a2227f2-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ce2e7227237a64b8bc0b5c27f018bfd2a2227f2-5 new file mode 100644 index 0000000..c6b0df0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ce2e7227237a64b8bc0b5c27f018bfd2a2227f2-5 @@ -0,0 +1 @@ +| \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6e53664c27b28370ee8680e4e4dfd139b43c2850-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6e53664c27b28370ee8680e4e4dfd139b43c2850-2 new file mode 100644 index 0000000..4bbe386 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6e53664c27b28370ee8680e4e4dfd139b43c2850-2 @@ -0,0 +1,2 @@ +AF;xs{ +K  \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6eb5eee33ab96304ffc66043a961108878b0565f-9 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6eb5eee33ab96304ffc66043a961108878b0565f-9 new file mode 100644 index 0000000..2d1ee9e --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6eb5eee33ab96304ffc66043a961108878b0565f-9 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 new file mode 100644 index 0000000..0737403 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/6ebb78761afbe6429fd06e8f0f9394cc8e061c59-6 @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/72677d19506938afc885d16fd5ca7c4be75f3752 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/72677d19506938afc885d16fd5ca7c4be75f3752 new file mode 100644 index 0000000000000000000000000000000000000000..ed8c6b506471be467ea240f13d3ac4f40d14051a GIT binary patch literal 5803 zcmeI0`#%%fTk&#C}m(EA|xc4Xf9GKS*eM;lWkQbR4k;Z4)YYlYE{t}BUj%!Qcq{?p6F41 zy>1;ldif1fx%6R@Hwzj_S2AUtFvUve9kT6q2hDF0P~uV>R_?{XW5{;FUzYk=ZE}8E z!bK4bUkoE&IikIBjDC5=WcpcwyNJPwhAiB*+n$NabgJ$t=WzHIzPFjggPVBHZsTVr zpD!O*$2N;sJFg}-|6QBpZTK{P#Lt_}lsIVEs=(fc z?aB(06$8I?Ebvb@Vjjxdb({oMnpsJcPMoXM@-S{4z5)s%QWu<`^Q8&$I}LBjILHg2 zxjx4%9srHh){*e&lX|9V0GJ#3+gxmwcZ-I&Pkn3&yDGW2zRBf6U~#6#eD{l^*ADQO zKvxeb0T*is7- zC@?u0cYPDaKN^M#(A(lbeHeQ+C9~APX}qCP3r|E8Ez=UaSOXn|xu2`iOuCMVq_c@R zYp7L8f-h%LI23!78R)BWqik;rZ96AuR<$}F+IxS1H?`4f$jc&H39?T)PXO^;;~+>u z@Jt=ozWm|E1Vqr2SMcq)21;zfrw#+65kF5}>s4!Pld?&Yq>fBfjdG>5SiNg+!R=(o z=IC$c&}I&8SPEUy7um+BhGhXjRgQLyRN0>Iq5>nJFCgHj!4^*6zo?*ps{&X%cE_5A z-4CpSR>f_U>#9!tj(riXE7gAFI39#X4!+5XGwC#u8)+K4f~H`V!&?SVmf*Qte|-ku zsARv%txAk^6tfJMnj z7GEfjCxozkz%gvhbsZ=f#Ypm6;s8ev0-487B}c!LerV1QkgzYQ>g;I(M$g~DRqx!* z#lv(vXFTqPj#8$~Q=^0<)%Jly?Y+!ASo3sV%4}Jx@ClIUy&|UL)MQO`SfAb!=pM=6 zNf$Z?zE5IOu9RU@+!P?oqyYT6!B*dEN6MCp&%o-roHRA%li6Hxq93^>Q>5@zb>1t> zvWW)pkvE6Q5vhB}cr_jS+^BOpArll-o=llrhT2>3g$}47czj{lp__dvPuBhGzZJ#- zXmfIeH@$CZ4FEe{Nbo_~D5Zw!elA)(Pb*J|rfdI)Mqnm_HqqFhy7PO-H@T=b#R2>kqNWYj<0j-^3eEesI$*gC>EF#mJ-2muSIo#l84YO}wl7~G^|C8|>>|R{ zzQP#DpMv){9|HfQN*rYY{aq4=?%Ka;##55k|MVO$#+nw_hK&RwjkZ5+yMRn|o_>4n z$R|6OOk$yn?^`FgOcH*F(T~*%eXse<9;La8;5Pl+hI5b&ZCm3`s$rLp)2+I+toQ4` zv@SX)oT2{0$jl%aXyv zp);W5z8sj_MwV@dU8HQn_`iZd6)PFqHup;#c9L0xluvjV_F^jXWp&D5=p1C5+&y1N zdpjG_Zt@34k(jZzx=xP|p$yc^vb~RFwgiMN`c|(t_C?AF?%GN|njeRVyQy1m74_XM z{?S@EtSE}5H;LRF{l7>^Hgo9bZ{I&QhXyias{I}uR4->{LHvGo98p8$3?I7%{{sl? BZtwsA literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/747d7c993787ae22ace6ec322dc1f098c938ec1f b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/747d7c993787ae22ace6ec322dc1f098c938ec1f new file mode 100644 index 0000000000000000000000000000000000000000..d37c3272249ea16a750d9fff56acdafc8cd54c76 GIT binary patch literal 2998 zcmds(SvVAo0)}TX_GN67eH}~LA{q?YGPW?IVlenM^sC91B@qTA`Y|N3CK^jgWDD8% zAK90YU(5^&$&xke`7h3MuFl1|Ip^YBeBbr=e9!ki&kHdGoSpFifX5(!6hK+ZKe{9N z=&}rqHHrlwBme*y5@P`X0Mp+BnS%ay0I>}Vf-{4S&43`N6fl*OKZ;4{H-Is+M`uxH zo~SA?_YM1q9U4beb6taYxOnjLbek-{*vK&W^;fr>YbQE+y{JtP#w&|&#!4ONnQ3RI zVWPDY0#D%0Zz>RR7wJ4Xd|tWh=X2$j(52zPzcQB_os3fO{6@NXr5I&mG$(?3uz!0t z9bd#YYa4AYJAA$d^Fx*Twvs?T2M=(7Y(3WLB|0nRCmTrkcK>xT%oujPlm#O5_>@uk z0ODH*T6ogAV)L|g0ftxvOR{KrzlgQ+e0cvYI{c4iNqFFg7+mXKxsGefCl|pk(XV3Q z^1EA2uH-64igLq|E%eT!PVAfpkn5mf^K(0+LC?z+Gm zT_1mwE1Ul4@hQjp8_yN$*e6TkPmPR!NB+4>*vMXh^v&KhYH}Y^rzdVgZT;mH^GHmQD%Y|Q%sG|_*0XI4Fh@1iH<*wf$ypfc_ear5dHi`bU7}~^9aSHJ$rvKmw@_+x z-_uhw?#Zf$nZ~-U4A~TagSGr~%MPJ;W&&tDO#pC1?>b`IM|Z&4rN>9hUm4+?OS zVyr6lcDEzPMeuUCHIF+=YomM9>MoZFtiuByTTL zkKlI}rPGW1?-w4jIS~Y!!RC18cnn|sr$D@s%0|4J+8^T$E8H1IPbi%21@LNu zwOzM-Yn=G-__|msM%8B>D(z;$hfco#n|8rBl7h-sk3s7DGM_fQfYg-edDi1_N8v&D zSGu2{CLTSD$BzmLMiV}$oy=5T4kAMLM2IF)*(Lb%%@KYz(^~Ub?YjF*E{aqZ7GsX` zw9oT3Jy^DLNXHrWup0f~YZ-$g9org?;E96d$B<1@y(U6F{`Rxf$>*VoAfa>i6_#!= zO>_N55An*@O=f7kX@(xfq8xW0nmu}m$sMwOP|s;8=E=$}m*ql8 zy>R)L{#r<0@VAu2`~CrOtiLQ%iJ@uWPBwi7y*p13r%y?qL0}0ApmNUKh_*4%@5RkO z*+=%6eR)+Zq31OeR~^1WCD*6@`a#xUBQVq`ws7CIoFT!0dYZC zWNpKpq)I;3;HnxyS+Cd+V(_jY66vnG@rSwZi?{doPI>jHVr1_z4lLwt{!$0A~$ zn`cayY3wOdk4dylgjw8j%$e12@Q$e@fb=mx(*;o}P8mNDR7S)cT~Tav7oW26_W94> zIW=91g5?+fUzM*XZnd%-L+LL6)zi_CuC!s?a77#HSwv{@h7neqT#XEM)ADJ z0nf4K*PVPOnM+@==m8{SAb}C+^Rd$t%}_M)Q|w!FdUm6-Z^ONJy9OEOk(Q8yy!xj@ zD$@i-Ovq+ghi+ljw3Q53ek-~u1c~28v4bMr>`?)kuWf?i3#V`fRudIV%l={28eC>A zE=6i)rlIq{u3#-IB*j#M2NAHLcesb=`ghx-MxvEG_Ym*Y?K`?{o`2|&@J<#V_pE-r z*>r6R5VTBj2kJ?y4kod^`dsKyTlDvAdtxWwj%7f&?1ohx&DPYKfJ_XtFvQ7JTO_SS zy@W*$nzhms?KH>h<|mj$eqqiiTwfJLthtl}2{w)u1X_;e7?(-dE}un5g&M4r}q=s{rXW zEkGPd%eL1p^n~VBNoc9`^I7U|M3?h$lVG^>)vf>f#hzE#TBd4_7U`R374vHoNiGf= zoBti3YtTV?xwk62LXeB9Wv=Nh%3dj^#-tD!xH7rW6iWmDpYv|NW3(QTbR%BcOa+B`x&swBJC<`88o0y3$5oBpXh)b-f<(ys{2gB}gMZbrJ z>!P#PIgEInoO@-nnY%EpTXV^pKMUN#NZ|Vv$txHha)h}Oogvxo8&T~$M8_IhpR}$7 znJyj`uqjE{9O3)>}Ei Fe*j;+j++1g literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 new file mode 100644 index 0000000..b5a4227 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/75262a4c69622c9103675c86a5e6a4a3688ed3e6-8 @@ -0,0 +1 @@ + 76 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/764ca341b24c6a68ad9507a31abcc33287f6c994-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/764ca341b24c6a68ad9507a31abcc33287f6c994-1 new file mode 100644 index 0000000..d520c28 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/764ca341b24c6a68ad9507a31abcc33287f6c994-1 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7b56b7ac07966b8060919498d93a47e68730d20a-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7b56b7ac07966b8060919498d93a47e68730d20a-2 new file mode 100644 index 0000000000000000000000000000000000000000..16fd1ce84a73a4c25be57525374606b102a91721 GIT binary patch literal 123 zcmV->0EGV%_yq+1e*u9XLty|8-xwqO4+slF0E9p|5Cj1bARq(*1VAW)U?3JE2qFFl z`42hdK^7SV+J9&$gVcFlq(^0ektp4NIXg6Ctt_MkHGYtR$ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 new file mode 100644 index 0000000..1aa4381 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/7bbcc6e3a846cb3bdfe20a0c4d34f30985ab87d3-1 @@ -0,0 +1 @@ +_!8L4Qժ?w(&R@´ 6ƹ\$=lƹP@6B)-=<䬣` \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8c562007589132e496325ea892733466e03a06cb b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8c562007589132e496325ea892733466e03a06cb new file mode 100644 index 0000000000000000000000000000000000000000..4440cd5e455ab515c95879b831d710a8c28875cb GIT binary patch literal 502 zcmVZ~VFBE?P!e!gRtbmh*R;6rathRe3W%r=X5wi!C)Z zo~$cMGa}Dg0+DJQlA7>4>g^h=Lav(nV}FX{27{yDk$wr|8HW>{l8Mv054Kd#hc!yl zXM`zzd>*jSxL$_|>7kR@X{@G4E5fy~r2$?%A4k5ve>r?TK0T9~PzrF(BM3?xzuh@i zoFzInh58DK*~L!Ud*-S%meI+1G-5Jfs>ieM#PfzeBo;KaRfrm_JeDTNYP>E7l<;_U sR0fm;x3k>XJ5A2Uo)?PIp!I&Tn3EIquItB@=t-C#);N7Dzm2Z#9@CEHtN;K2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8e78a58162034efce763c158087c6f1e427c1260 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/8e78a58162034efce763c158087c6f1e427c1260 new file mode 100644 index 0000000000000000000000000000000000000000..b6b0522b6bd5dc03066e64a52a8d2d1a6f15b956 GIT binary patch literal 94 zcmV-k0HOaA@c;k+o3LOYJbn!#{2vJ~A>o$<6A6(32}sJsaIFRDrn<0H^Taocsv~<{ zr6hySK13zuyCK`N-hoRA}0Wf$KJHUXG$_xTdmQDoW;X0`&4gvx2 zT!2PcSeQQZ$$$!AYsUdyG7P`~KouwSHy9Mb2^Lmi>jDEHuId;SG~?|0;AP3>X|6Y` z?uH8ve8%k_vFqO@KlGk)>FW0?_Y41!URr)=?!iERVK}Ntx;!#*_*}YyMVksSA^= z?r_oDxN8#QRCu;QZUaMgFqGjzwxPFS$68f}`o52+DZs2Nt0AGKj=c&=;_9f(br=_Ky1@yb{;L+hu60;XX z7ET3hTnx1&&=cR^l0>zqG5OoqDp_@k#rgDKhd&Y0cjVq8O+AIG(IZ|o zdz5H+QU1;p`DG7LCF|zlve#Snln$!HqpH`F-58LN*!OA&kDEBhv(-8?Bq9LBc)pSi?chG#F(B# zD~ns4_+w;EJ&5qI=T=@Q?mcb2Ij0d^rZ)=)L1ZH~eH+NQmVm0x2~zRu0}C5&dacq~J-0&pL1X9wd9TI2cq^dNw z4IfiIJ?!F2*UX0$El@GS)KUF%>#(8_LUXRm1*QopYA*)NUXzHZNo!Nr&I zGI&l$wLWEMc~YG-|5GXF%%(^Rv{o@ro+18L5nd($ym&E;oy)PqKT_A`Q`q-z)L6Is zF1v-d0|}`1Gl`N$&3RHNk=w7NFxp1)F-5@~rDP+C?F-h3T!b_QuV1p2^9T1h^&n9!Ts$#xZIh-$# zr6mtyX;Z@aHgNOv@bdA@P%zI<Ln#=|E*{tYmf4O!#9ru%%<< zN80>AF=wBFvcYeqVtj?wMzBHQYwTSV{92t#B3qH200Oamb+5E1k*2KVj9tRYC&CM6 zS8lGnT#*+>{^aL>8ut;ppVl(;pvOhfw7xk0VXjKxg1MqG zpr#MGRAXFiYXV3+r9)MB`GFlO)u>8&A&4_L-7q51!s9enDU*Ty55SvtiN%~o`z^BH zThFDvmUgdo$mXL2%icNSd(W%4CU~Aojth?$`tp->>Hbv-vzte3YtQy`3*uiK%6}CJ ztX!o9@m2zf+0G!Yw!d+#+TCjVle|<>ae=Pk8&FeKan$~ka_B%bpGJDYh`;^dk68Cy zAz7q6Nsq5>PfIqc z8x?UVlpZLjdD>JZ-74{oh^y9=L^HX|N2v5OBKQA?$yB#TGRaFHNA^M&0@uZDCE%yrm-KkqdngZkLNR+Dl!!0`!4@20SI`i z(z|Ke*r*U`kky_b8tUsTz_8xs&PNJVjvOCn9X!#>n@~e0&en_-ExDZ`TzbVTW!O-FX;Ivbwy%%Onl%nZUVFuS5pXi-rZxM0{OCLX*INSTSs|dJ|Nikg zA53+c|IPJjI4+Q1@#^P!cXyzT{%)+PKv!R*JEYYbjj!g%+fVx^Tp!g{DBIPvG->E` z9GB*TLv5_o8k`+bc-9HQ7p$LOaRl%YPD0sRyK2;#KK##6&Nkb4uD&4UVWVql=a!$} z^BXclu)jwW_LZ53H$AanSVF_I-!`@^*O4#6Ohp1#9;`AXZWDxSu?A$N|L$SUos1vTv0;6fgP#@bev$TgyY3gBLnKbDYS@>&>9@l=={=>hovN$V70@e ziZ}=3ay;V%s=Jw^$=&~dB>t};(e}ft7J^(H=04rppONz@y1=piZ-Vw*1YNzt`V1wc>%Xxc}Naa4so~{x6KvbvG zrTWiS2R?=yEp+OeqdbsU?o+Op$1SS-tthieI;;ZTc$>M(Ye8?glh(0x9Lp-ElO}8_ z`tWGaZShX)aGz~!zBlyFFyd(R!dM7Sge$7EgUEYl&=OaspC%#tU>6oT>R&F# zZ5)}j)|F^|Pbz`kNRCO>3Mx`(OWdhZe1zkrmwrveD1RDK-E}2%FiF`*_f&8cwaF!p~ubS zU1i4Lkp0Ysi*m^VX_&Fm69a#7su$D??qs?tW@CQ3p}a@htl2hwc8?oujpc ui2{SPzJS;s%3L)Hr}2Y+uxSpEY#q)W^I literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/9300f0f580a7b8b7cb3a7163a48ed0771c72fb1b new file mode 100644 index 0000000000000000000000000000000000000000..c5cc8a95749adc309bcfaf6bca3dc0da7131a1d0 GIT binary patch literal 466 zcmXpO`0)Qf1Ir&K21Wx9tA4LliBifn2_gzk3JeYc4F@1!UO7#qiJkp+k>>ZRibJI{r4&n~u5MzB zz4k)w66f{_-JdGLHmILxi?4Ivp%<*&;dX?dV-_J!2mJf*n>+&eY;(^;!O<$QQr-tyYW z)aixEs?>=#f3KTxzKU0lsZ8TsrC%3itTHcgRcB~&WWULcV`nDtv(0VN|M2I>qR7=k z1f6zG?t$eI_Ig!Odp)1Rd6#=ueK#}H*y8B5+2n4*wD+HMG+Frhwml7c_w@tF{s{s5 z8g6~GK=^wq`>kuQ7MSdDjb1Y)bz`V~-V%1sURB*4mv@@Y|GOvJn8oK@$i-LNr$~$6 z)cv+6rte$SWz9twj{eVct=(JTY`bZr=tsF}H<^l7YR{c1B@&zS=i^k##Vn6*rC+UF mko)3T#r?N?nT#(9$$Oo7^OoO`!C|kJ$Ajm>Ys~-sX9fU+wDE8=Avlj3?mvh7fb zM%HSMgBoG6jDi#QywAIyn9V+S?Jn0~p645`y=Jl6IBD6swQ@#}BZ636Tt4la?V4m) zvhDa*sYI^!t#RrXI;WbH=6; zSFhja_Ss&(teD%Vs4IE--nA3gA7D7O=!BW98H3M}8zFkHzL>mwKg(3HZPmF)iRX%C zr{0+HR%Hmxua&#^lfUjfJ^vlY zH^=6~OLv{al)ucGa>kVP?^=mvZBw#teq=uQVNue&8}~zQw%z7rTD^Y1(;7B*N!vn;_fYx zbvLxVmFG!b%4h1DU3%MVo#jI1ll^V%(yz>!w==s*UTV3`xa(N$-A!S$moM_U_FS)i zm+}pEUcTwCtgy(dPcXbL@@0F{45^@1smJ+Q4tIA|Ce;V0O6RF_tl9UEi<5cntB3*t zAB)IO*{ps198bN)zqwRIe=WOR#o2ei%xl6|%XA0t(3_v0Z`?6+p428)*P;!J!n=$+ z1iHAr7CG!^SE{?RTEF_+)LSoZz3`iil~Vie z({k&k+6xZ~R<1KHuuhnw=(|I9K{iajgh{g4*Rfu^ZKdMUsIor}276Y_Q2%Bgy6s_E z(}7p7*H19Gu&R%h{b0*v)%{@)el!H^D@pWk*&dp|eeLuIKXR9|M9wc}a~aLSqd6Fn O!$)&4Y7X9Tjt2lj*};ea literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/b62b1d73848fde9b74a166239cef1a76506a9e41-1 new file mode 100644 index 0000000000000000000000000000000000000000..e40482bb81380d86efb67decabce595be6a7ede6 GIT binary patch literal 1097 zcmWf6Anwq>D!{tI>t&y6&E#6?y7}EJ`!&52Jd{5yyuNi+x{R{m z&eSZM&I7mRELGQMlkIx?Vg2G5)nLV~8P{U}md`e^@x2iIcJ=p_EY-p5XYZ6O>`UJL z|FuT=$q*0SS*79sw~F}+e+l{hs#fdZy(_QN^4#V;zVYtA)u~V;(V*_MyI1SCdmg^b zVtaL8)qJlF=3jTsoGtj=V%zWieMM7!TCXgMEdLsxebL0xf9v{t%Z1+f?#+9acEqyp z?LU$nk(k@!BGt&hcU`FMV~Nfay1|b}8WgE_w~i!(1aek60e?Em$^b(2<3 zh%$M-?%!@-sd;L6!#}Ef8J6I`dt!B(*-(t2WvlX(cBy*}Xo@@kuOo&}P(rmU{QG}X z!KuP~(No-Jd!^~lEN-2TuKun6>hb&%W{P{$f8wb?W8k8S(*NWc>n+a literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/bedb6456c65af2ca319c6630db22f2e362dd73f2-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/bedb6456c65af2ca319c6630db22f2e362dd73f2-5 new file mode 100644 index 0000000..1be3f79 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/bedb6456c65af2ca319c6630db22f2e362dd73f2-5 @@ -0,0 +1 @@ +V \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 new file mode 100644 index 0000000..fe2ec62 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c0a4a69dff77a11d744507864de0a15d000afd3f-5 @@ -0,0 +1 @@ +)tZ럗EdEs/@& \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c2d596d0601332a809c19c0347580c78b079f822-8 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c2d596d0601332a809c19c0347580c78b079f822-8 new file mode 100644 index 0000000..69531c1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c2d596d0601332a809c19c0347580c78b079f822-8 @@ -0,0 +1 @@ +$$$ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 new file mode 100644 index 0000000..198232f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c3d814235d50a4f96ced41bf5fc9c53c4e408765 @@ -0,0 +1 @@ +"O|LP;_(<7CP](G#\A_ٮK" \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 new file mode 100644 index 0000000..7349f4b --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c43bfe87577eecc822788ffeb9dadf2cd7b8d2f0 @@ -0,0 +1 @@ +aG43FMuuxo /!in;. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d new file mode 100644 index 0000000..d932584 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/c7198f2cc1dd9bffea474e6eb4b189ecdf2f965d @@ -0,0 +1 @@ +#_!C<37g0TmFCCPixKT|of>1tJPcks@7@gwRn4 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-9 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-9 new file mode 100644 index 0000000..e69de29 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da3ec0c217bfb46b23a5044192571ae8eb5bd2b7-9 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/da3ec0c217bfb46b23a5044192571ae8eb5bd2b7-9 new file mode 100644 index 0000000000000000000000000000000000000000..074a79ef7f46d5e62b16896c47efeff4a0766b1a GIT binary patch literal 4 LcmY$YXJ7yT0to=3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 new file mode 100644 index 0000000..c76fd42 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/dbada9d56b10891ca136d80794bb93ad9e58293a-7 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de0ea11f2f9d6c773542b53337f688d655918f76-7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de0ea11f2f9d6c773542b53337f688d655918f76-7 new file mode 100644 index 0000000..069748b --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de0ea11f2f9d6c773542b53337f688d655918f76-7 @@ -0,0 +1 @@ +Ўt \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de15b9702bd007145d26f7b5ddea83a93ecee381-5 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de15b9702bd007145d26f7b5ddea83a93ecee381-5 new file mode 100644 index 0000000000000000000000000000000000000000..f096d2f9d97a5f456d4b1463b99d3a13406a1e37 GIT binary patch literal 9 QcmWfB!oV0b=fVH~01<%%#Q*>R literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 new file mode 100644 index 0000000..9c3fc0f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/de357612a902159ac2a91a9cd6b0d7287d55e968-6 @@ -0,0 +1 @@ +ojY \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 new file mode 100644 index 0000000..8d1f001 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/decd27d54bcedc965463c545a051f44c140cfb6b-3 @@ -0,0 +1 @@ +Pd. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 new file mode 100644 index 0000000..5a40da0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e0355b1d80ab87e740c6493abf4b7e532c89d3a6-2 @@ -0,0 +1 @@ +% ɟ.A9OE \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e395861f9b34c58744c48a34a0d471241957cec5-2 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/e395861f9b34c58744c48a34a0d471241957cec5-2 new file mode 100644 index 0000000000000000000000000000000000000000..47c4a3f6cc8b6b90f3809c6cbc2a0d175d71e142 GIT binary patch literal 26 hcmea&VPIllVANq?D01UtY z0K*VWCjcQ11f>xm0HOjgMVN)g0iN95+G39W_%CYO?I(})JQBg}+He0zW*8*3v;_~= zmjTyw%gK1Y*KH6#SBH;i#g4jCbf+I(%5CMEnzf8+&K6ovjxXOZIc?&x}VL+0~=V)OhfS5AGrVQK=FC>PDTYqzt{NR0^7E#J amnE1B?PNPq#NIjA{Op;S*N!laAEf}<`%vKk literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ec8f2472897dd80c1c5f5c958c665d18a8602e55-10 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ec8f2472897dd80c1c5f5c958c665d18a8602e55-10 new file mode 100644 index 0000000000000000000000000000000000000000..ee36893a6847ad5a0dcda3cb50240962cfe51454 GIT binary patch literal 4 LcmdNCV5kQG0apOI literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 new file mode 100644 index 0000000..329b60d --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/ed6e6eea47cde68b49dcadd93eb14cb6db432ff2-7 @@ -0,0 +1 @@ +?k \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/f62ba7c4e99c6ba70e8f457f28ef45f797b9992a-1 new file mode 100644 index 0000000000000000000000000000000000000000..22679854578939002ffe77b01849e87e178c9b57 GIT binary patch literal 250 zcmV)=b098=kMWjhQK~j->^L}t}eiQ zRRlyBbKxsJfE79qT?YM*bxKbBEpggkvQN~`QF_J=H0EGX72>$;cAo!O!kb^Le#5jTv001Bm1ONyE5HJEDFaiLC!9o}a0RjL51uQLy z0dRXJfotPbA00Ie~ dx2H1Hx?ssHgdIH8K${l@PQs!B1KFpm_y^*bF^&KL literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fad75398a55edd191340909bf867610b6bc72ff7 new file mode 100644 index 0000000000000000000000000000000000000000..8197d4e687ac67ebe2eb5fc1055acefd7f259b8f GIT binary patch literal 231 zcmVk!B8N9b;hoMKS<~dM!NjX<^dx<@j$}M5`T0NMY6jPU>e|5Fe;V;n^G|9|UuAY}8e&{UG){^9^g=gyHZx1U%e0=lRbUjP6A literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fdd2a48761f050f1f83fa279882eee5c8378f9d9-3 b/vendor/github.com/klauspost/compress/fse/fuzz/decompress/corpus/fdd2a48761f050f1f83fa279882eee5c8378f9d9-3 new file mode 100644 index 0000000000000000000000000000000000000000..8d106f4cd9bc9320a9b87d599ca3ba1bc6264948 GIT binary patch literal 49 zcmWf6AS>|T|Nrd{3?_#@H0*HbRJbN!<2h-L(V_qQlUFSIR6q4U2;?XJ1(K#A`7Z&V Ch8>~+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/run-compress.cmd b/vendor/github.com/klauspost/compress/fse/fuzz/run-compress.cmd new file mode 100644 index 0000000..2369fe2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/run-compress.cmd @@ -0,0 +1,4 @@ +cd .. +go-fuzz-build -tags=compress github.com/klauspost/compress/fse +cd fuzz +go-fuzz -bin=../fse-fuzz.zip -workdir=compress -procs=4 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz/run-decompress.cmd b/vendor/github.com/klauspost/compress/fse/fuzz/run-decompress.cmd new file mode 100644 index 0000000..d2ed1f2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz/run-decompress.cmd @@ -0,0 +1,4 @@ +cd .. +go-fuzz-build -tags=decompress github.com/klauspost/compress/fse +cd fuzz +go-fuzz -bin=../fse-fuzz.zip -workdir=decompress -procs=4 diff --git a/vendor/github.com/klauspost/compress/fse/fuzz_compress.go b/vendor/github.com/klauspost/compress/fse/fuzz_compress.go new file mode 100644 index 0000000..96f0fb8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz_compress.go @@ -0,0 +1,25 @@ +// +build gofuzz,compress + +package fse + +import ( + "bytes" +) + +func Fuzz(data []byte) int { + comp, err := Compress(data, nil) + if err == ErrIncompressible || err == ErrUseRLE { + return 0 + } + if err != nil { + panic(err) + } + dec, err := Decompress(comp, nil) + if err != nil { + panic(err) + } + if !bytes.Equal(data, dec) { + panic("decoder mismatch") + } + return 1 +} diff --git a/vendor/github.com/klauspost/compress/fse/fuzz_decompress.go b/vendor/github.com/klauspost/compress/fse/fuzz_decompress.go new file mode 100644 index 0000000..ed10218 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fuzz_decompress.go @@ -0,0 +1,19 @@ +// +build gofuzz,decompress + +package fse + +import "strings" + +func Fuzz(data []byte) int { + dec, err := Decompress(data, nil) + if err != nil && strings.Contains(err.Error(), "DecompressLimit") { + panic(err) + } + if err != nil { + return 0 + } + if len(dec) == 0 { + panic("no output") + } + return 1 +} diff --git a/vendor/github.com/klauspost/compress/fse/highbit_go19.go b/vendor/github.com/klauspost/compress/fse/highbit_go19.go new file mode 100644 index 0000000..e16ecd5 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/highbit_go19.go @@ -0,0 +1,9 @@ +// +build go1.9 + +package fse + +import "math/bits" + +func highBits(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} diff --git a/vendor/github.com/klauspost/compress/fse/highbit_old.go b/vendor/github.com/klauspost/compress/fse/highbit_old.go new file mode 100644 index 0000000..7bb313a --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/highbit_old.go @@ -0,0 +1,18 @@ +// +build !go1.9 + +package fse + +var deBruijnClz = [...]uint8{0, 9, 1, 10, 13, 21, 2, 29, + 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, + 19, 27, 23, 6, 26, 5, 4, 31} + +// highBits returns the highest set bit +func highBits(v uint32) (n uint32) { + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + return uint32(deBruijnClz[(v*0x07C4ACDD)>>27]) +} diff --git a/vendor/github.com/klauspost/compress/gzip/example_test.go b/vendor/github.com/klauspost/compress/gzip/example_test.go index e32346b..ce29e9b 100644 --- a/vendor/github.com/klauspost/compress/gzip/example_test.go +++ b/vendor/github.com/klauspost/compress/gzip/example_test.go @@ -98,7 +98,7 @@ func ExampleReader_Multistream() { log.Fatal(err) } - fmt.Println("\n") + fmt.Print("\n\n") err = zr.Reset(&buf) if err == io.EOF { diff --git a/vendor/github.com/klauspost/compress/gzip/gunzip.go b/vendor/github.com/klauspost/compress/gzip/gunzip.go index e73fab3..568b5d4 100644 --- a/vendor/github.com/klauspost/compress/gzip/gunzip.go +++ b/vendor/github.com/klauspost/compress/gzip/gunzip.go @@ -10,11 +10,11 @@ import ( "bufio" "encoding/binary" "errors" + "hash/crc32" "io" "time" "github.com/klauspost/compress/flate" - "github.com/klauspost/crc32" ) const ( diff --git a/vendor/github.com/klauspost/compress/gzip/gunzip_test.go b/vendor/github.com/klauspost/compress/gzip/gunzip_test.go index c200ab1..bc7ca92 100644 --- a/vendor/github.com/klauspost/compress/gzip/gunzip_test.go +++ b/vendor/github.com/klauspost/compress/gzip/gunzip_test.go @@ -680,3 +680,37 @@ func BenchmarkGunzipStdlib(b *testing.B) { } } } +func TestTruncatedGunzip(t *testing.T) { + in := []byte(strings.Repeat("ASDFASDFASDFASDFASDF", 1000)) + var buf bytes.Buffer + enc := NewWriter(&buf) + _, err := enc.Write(in) + if err != nil { + t.Fatal(err) + } + enc.Close() + testdata := buf.Bytes() + for i := 5; i < len(testdata); i += 10 { + timer := time.NewTimer(time.Second) + done := make(chan struct{}) + fail := make(chan struct{}) + go func() { + r, err := NewReader(bytes.NewBuffer(testdata[:i])) + if err == nil { + b, err := ioutil.ReadAll(r) + if err == nil && !bytes.Equal(testdata[:i], b) { + close(fail) + } + } + close(done) + }() + select { + case <-timer.C: + t.Fatal("Timeout decoding") + case <-fail: + t.Fatal("No error, but mismatch") + case <-done: + timer.Stop() + } + } +} diff --git a/vendor/github.com/klauspost/compress/gzip/gzip.go b/vendor/github.com/klauspost/compress/gzip/gzip.go index a0f3ed0..7da7ee7 100644 --- a/vendor/github.com/klauspost/compress/gzip/gzip.go +++ b/vendor/github.com/klauspost/compress/gzip/gzip.go @@ -7,10 +7,10 @@ package gzip import ( "errors" "fmt" + "hash/crc32" "io" "github.com/klauspost/compress/flate" - "github.com/klauspost/crc32" ) // These constants are copied from the flate package, so that code that imports diff --git a/vendor/github.com/klauspost/compress/huff0/.gitignore b/vendor/github.com/klauspost/compress/huff0/.gitignore new file mode 100644 index 0000000..b3d2629 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/.gitignore @@ -0,0 +1 @@ +/huff0-fuzz.zip diff --git a/vendor/github.com/klauspost/compress/huff0/bitreader.go b/vendor/github.com/klauspost/compress/huff0/bitreader.go new file mode 100644 index 0000000..7d0903c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/bitreader.go @@ -0,0 +1,115 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package huff0 + +import ( + "errors" + "io" +) + +// bitReader reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReader struct { + in []byte + off uint // next byte to read is at in[off - 1] + value uint64 + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReader) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + b.off = uint(len(in)) + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + b.fill() + b.fill() + b.bitsRead += 8 - uint8(highBit32(uint32(v))) + return nil +} + +// getBits will return n bits. n can be 0. +func (b *bitReader) getBits(n uint8) uint16 { + if n == 0 || b.bitsRead >= 64 { + return 0 + } + return b.getBitsFast(n) +} + +// getBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReader) getBitsFast(n uint8) uint16 { + const regMask = 64 - 1 + v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) + b.bitsRead += n + return v +} + +// peekBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReader) peekBitsFast(n uint8) uint16 { + const regMask = 64 - 1 + v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) + return v +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReader) fillFast() { + if b.bitsRead < 32 { + return + } + // Do single re-slice to avoid bounds checks. + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReader) fill() { + if b.bitsRead < 32 { + return + } + if b.off > 4 { + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 + return + } + for b.off > 0 { + b.value = (b.value << 8) | uint64(b.in[b.off-1]) + b.bitsRead -= 8 + b.off-- + } +} + +// finished returns true if all bits have been read from the bit stream. +func (b *bitReader) finished() bool { + return b.off == 0 && b.bitsRead >= 64 +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReader) close() error { + // Release reference. + b.in = nil + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/huff0/bitwriter.go b/vendor/github.com/klauspost/compress/huff0/bitwriter.go new file mode 100644 index 0000000..c9d8e0e --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/bitwriter.go @@ -0,0 +1,176 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package huff0 + +import "fmt" + +// bitWriter will write bits. +// First bit will be LSB of the first byte of output. +type bitWriter struct { + bitContainer uint64 + nBits uint8 + out []byte +} + +// bitMask16 is bitmasks. Has extra to avoid bounds check. +var bitMask16 = [32]uint16{ + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF} /* up to 16 bits */ + +// addBits16NC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16NC(value uint16, bits uint8) { + b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) encSymbol(ct cTable, symbol byte) { + enc := ct[symbol] + b.bitContainer |= uint64(enc.val) << (b.nBits & 63) + b.nBits += enc.nBits +} + +// addBits16ZeroNC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +// This is fastest if bits can be zero. +func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) { + if bits == 0 { + return + } + value <<= (16 - bits) & 15 + value >>= (16 - bits) & 15 + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// flush will flush all pending full bytes. +// There will be at least 56 bits available for writing when this has been called. +// Using flush32 is faster, but leaves less space for writing. +func (b *bitWriter) flush() { + v := b.nBits >> 3 + switch v { + case 0: + case 1: + b.out = append(b.out, + byte(b.bitContainer), + ) + case 2: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + ) + case 3: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + ) + case 4: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + ) + case 5: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + ) + case 6: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + ) + case 7: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + ) + case 8: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + byte(b.bitContainer>>56), + ) + default: + panic(fmt.Errorf("bits (%d) > 64", b.nBits)) + } + b.bitContainer >>= v << 3 + b.nBits &= 7 +} + +// flush32 will flush out, so there are at least 32 bits available for writing. +func (b *bitWriter) flush32() { + if b.nBits < 32 { + return + } + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24)) + b.nBits -= 32 + b.bitContainer >>= 32 +} + +// flushAlign will flush remaining full bytes and align to next byte boundary. +func (b *bitWriter) flushAlign() { + nbBytes := (b.nBits + 7) >> 3 + for i := uint8(0); i < nbBytes; i++ { + b.out = append(b.out, byte(b.bitContainer>>(i*8))) + } + b.nBits = 0 + b.bitContainer = 0 +} + +// close will write the alignment bit and write the final byte(s) +// to the output. +func (b *bitWriter) close() error { + // End mark + b.addBits16Clean(1, 1) + // flush until next byte. + b.flushAlign() + return nil +} + +// reset and continue writing by appending to out. +func (b *bitWriter) reset(out []byte) { + b.bitContainer = 0 + b.nBits = 0 + b.out = out +} diff --git a/vendor/github.com/klauspost/compress/huff0/bytereader.go b/vendor/github.com/klauspost/compress/huff0/bytereader.go new file mode 100644 index 0000000..50bcdf6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/bytereader.go @@ -0,0 +1,54 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package huff0 + +// byteReader provides a byte reader that reads +// little endian values from a byte stream. +// The input stream is manually advanced. +// The reader performs no bounds checks. +type byteReader struct { + b []byte + off int +} + +// init will initialize the reader and set the input. +func (b *byteReader) init(in []byte) { + b.b = in + b.off = 0 +} + +// advance the stream b n bytes. +func (b *byteReader) advance(n uint) { + b.off += int(n) +} + +// Int32 returns a little endian int32 starting at current offset. +func (b byteReader) Int32() int32 { + v3 := int32(b.b[b.off+3]) + v2 := int32(b.b[b.off+2]) + v1 := int32(b.b[b.off+1]) + v0 := int32(b.b[b.off]) + return (v3 << 24) | (v2 << 16) | (v1 << 8) | v0 +} + +// Uint32 returns a little endian uint32 starting at current offset. +func (b byteReader) Uint32() uint32 { + v3 := uint32(b.b[b.off+3]) + v2 := uint32(b.b[b.off+2]) + v1 := uint32(b.b[b.off+1]) + v0 := uint32(b.b[b.off]) + return (v3 << 24) | (v2 << 16) | (v1 << 8) | v0 +} + +// unread returns the unread portion of the input. +func (b byteReader) unread() []byte { + return b.b[b.off:] +} + +// remain will return the number of bytes remaining. +func (b byteReader) remain() int { + return len(b.b) - b.off +} diff --git a/vendor/github.com/klauspost/compress/huff0/compress.go b/vendor/github.com/klauspost/compress/huff0/compress.go new file mode 100644 index 0000000..22bee74 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/compress.go @@ -0,0 +1,600 @@ +package huff0 + +import ( + "fmt" + "runtime" + "sync" +) + +func Compress1X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) { + s, err = s.prepare(in) + if err != nil { + return nil, false, err + } + return compress(in, s, s.compress1X) +} + +func Compress4X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) { + s, err = s.prepare(in) + if err != nil { + return nil, false, err + } + if false { + // TODO: compress4Xp only slightly faster. + const parallelThreshold = 8 << 10 + if len(in) < parallelThreshold || runtime.GOMAXPROCS(0) == 1 { + return compress(in, s, s.compress4X) + } + return compress(in, s, s.compress4Xp) + } + return compress(in, s, s.compress4X) +} + +func compress(in []byte, s *Scratch, compressor func(src []byte) ([]byte, error)) (out []byte, reUsed bool, err error) { + // Nuke previous table if we cannot reuse anyway. + if s.Reuse == ReusePolicyNone { + s.prevTable = s.prevTable[:0] + } + + // Create histogram, if none was provided. + maxCount := s.maxCount + var canReuse = false + if maxCount == 0 { + maxCount, canReuse = s.countSimple(in) + } else { + canReuse = s.canUseTable(s.prevTable) + } + + // Reset for next run. + s.clearCount = true + s.maxCount = 0 + if maxCount >= len(in) { + if maxCount > len(in) { + return nil, false, fmt.Errorf("maxCount (%d) > length (%d)", maxCount, len(in)) + } + // One symbol, use RLE + return nil, false, ErrUseRLE + } + if maxCount == 1 || maxCount < (len(in)>>7) { + // Each symbol present maximum once or too well distributed. + return nil, false, ErrIncompressible + } + + if s.Reuse == ReusePolicyPrefer && canReuse { + keepTable := s.cTable + s.cTable = s.prevTable + s.Out, err = compressor(in) + s.cTable = keepTable + if err == nil && len(s.Out) < len(in) { + s.OutData = s.Out + return s.Out, true, nil + } + // Do not attempt to re-use later. + s.prevTable = s.prevTable[:0] + } + + // Calculate new table. + s.optimalTableLog() + err = s.buildCTable() + if err != nil { + return nil, false, err + } + + if !s.canUseTable(s.cTable) { + // TODO: Not needed. + panic("invalid table generated") + } + + if s.Reuse == ReusePolicyAllow && canReuse { + hSize := len(s.Out) + oldSize := s.prevTable.estimateSize(s.count[:s.symbolLen]) + newSize := s.cTable.estimateSize(s.count[:s.symbolLen]) + if oldSize <= hSize+newSize || hSize+12 >= len(in) { + // Retain cTable even if we re-use. + keepTable := s.cTable + s.cTable = s.prevTable + s.Out, err = compressor(in) + s.cTable = keepTable + if len(s.Out) >= len(in) { + return nil, false, ErrIncompressible + } + s.OutData = s.Out + return s.Out, true, nil + } + } + + // Use new table + s.cTable.write(s) + s.OutTable = s.Out + + // Compress using new table + s.Out, err = compressor(in) + if err != nil { + s.OutTable = nil + return nil, false, err + } + if len(s.Out) >= len(in) { + s.OutTable = nil + return nil, false, ErrIncompressible + } + // Move current table into previous. + s.prevTable, s.cTable = s.cTable, s.prevTable[:0] + s.OutData = s.Out[len(s.OutTable):] + return s.Out, false, nil +} + +func (s *Scratch) compress1X(src []byte) ([]byte, error) { + return s.compress1xDo(s.Out, src) +} + +func (s *Scratch) compress1xDo(dst, src []byte) ([]byte, error) { + var bw = bitWriter{out: dst} + + // N is length divisible by 4. + n := len(src) + n -= n & 3 + cTable := s.cTable[:256] + + // Encode last bytes. + for i := len(src) & 3; i > 0; i-- { + bw.encSymbol(cTable, src[n+i-1]) + } + if s.actualTableLog <= 8 { + n -= 4 + for ; n >= 0; n -= 4 { + tmp := src[n : n+4] + // tmp should be len 4 + bw.flush32() + bw.encSymbol(cTable, tmp[3]) + bw.encSymbol(cTable, tmp[2]) + bw.encSymbol(cTable, tmp[1]) + bw.encSymbol(cTable, tmp[0]) + } + } else { + n -= 4 + for ; n >= 0; n -= 4 { + tmp := src[n : n+4] + // tmp should be len 4 + bw.flush32() + bw.encSymbol(cTable, tmp[3]) + bw.encSymbol(cTable, tmp[2]) + bw.flush32() + bw.encSymbol(cTable, tmp[1]) + bw.encSymbol(cTable, tmp[0]) + } + } + err := bw.close() + return bw.out, err +} + +var sixZeros [6]byte + +func (s *Scratch) compress4X(src []byte) ([]byte, error) { + if len(src) < 12 { + return nil, ErrIncompressible + } + segmentSize := (len(src) + 3) / 4 + + // Add placeholder for output length + offsetIdx := len(s.Out) + s.Out = append(s.Out, sixZeros[:]...) + + for i := 0; i < 4; i++ { + toDo := src + if len(toDo) > segmentSize { + toDo = toDo[:segmentSize] + } + src = src[len(toDo):] + + var err error + idx := len(s.Out) + s.Out, err = s.compress1xDo(s.Out, toDo) + if err != nil { + return nil, err + } + // Write compressed length as little endian before block. + if i < 3 { + // Last length is not written. + length := len(s.Out) - idx + s.Out[i*2+offsetIdx] = byte(length) + s.Out[i*2+offsetIdx+1] = byte(length >> 8) + } + } + + return s.Out, nil +} + +// compress4Xp will compress 4 streams using separate goroutines. +func (s *Scratch) compress4Xp(src []byte) ([]byte, error) { + if len(src) < 12 { + return nil, ErrIncompressible + } + // Add placeholder for output length + s.Out = s.Out[:6] + + segmentSize := (len(src) + 3) / 4 + var wg sync.WaitGroup + var errs [4]error + wg.Add(4) + for i := 0; i < 4; i++ { + toDo := src + if len(toDo) > segmentSize { + toDo = toDo[:segmentSize] + } + src = src[len(toDo):] + + // Separate goroutine for each block. + go func(i int) { + s.tmpOut[i], errs[i] = s.compress1xDo(s.tmpOut[i][:0], toDo) + wg.Done() + }(i) + } + wg.Wait() + for i := 0; i < 4; i++ { + if errs[i] != nil { + return nil, errs[i] + } + o := s.tmpOut[i] + // Write compressed length as little endian before block. + if i < 3 { + // Last length is not written. + s.Out[i*2] = byte(len(o)) + s.Out[i*2+1] = byte(len(o) >> 8) + } + + // Write output. + s.Out = append(s.Out, o...) + } + return s.Out, nil +} + +// countSimple will create a simple histogram in s.count. +// Returns the biggest count. +// Does not update s.clearCount. +func (s *Scratch) countSimple(in []byte) (max int, reuse bool) { + reuse = true + for _, v := range in { + s.count[v]++ + } + m := uint32(0) + if len(s.prevTable) > 0 { + for i, v := range s.count[:] { + if v > m { + m = v + } + if v > 0 { + s.symbolLen = uint16(i) + 1 + if i >= len(s.prevTable) { + reuse = false + } else { + if s.prevTable[i].nBits == 0 { + reuse = false + } + } + } + } + return int(m), reuse + } + for i, v := range s.count[:] { + if v > m { + m = v + } + if v > 0 { + s.symbolLen = uint16(i) + 1 + } + } + return int(m), false +} + +func (s *Scratch) canUseTable(c cTable) bool { + if len(c) < int(s.symbolLen) { + return false + } + for i, v := range s.count[:s.symbolLen] { + if v != 0 && c[i].nBits == 0 { + return false + } + } + return true +} + +// minTableLog provides the minimum logSize to safely represent a distribution. +func (s *Scratch) minTableLog() uint8 { + minBitsSrc := highBit32(uint32(s.br.remain()-1)) + 1 + minBitsSymbols := highBit32(uint32(s.symbolLen-1)) + 2 + if minBitsSrc < minBitsSymbols { + return uint8(minBitsSrc) + } + return uint8(minBitsSymbols) +} + +// optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog +func (s *Scratch) optimalTableLog() { + tableLog := s.TableLog + minBits := s.minTableLog() + maxBitsSrc := uint8(highBit32(uint32(s.br.remain()-1))) - 2 + if maxBitsSrc < tableLog { + // Accuracy can be reduced + tableLog = maxBitsSrc + } + if minBits > tableLog { + tableLog = minBits + } + // Need a minimum to safely represent all symbol values + if tableLog < minTablelog { + tableLog = minTablelog + } + if tableLog > tableLogMax { + tableLog = tableLogMax + } + s.actualTableLog = tableLog +} + +type cTableEntry struct { + val uint16 + nBits uint8 + // We have 8 bits extra +} + +const huffNodesMask = huffNodesLen - 1 + +func (s *Scratch) buildCTable() error { + if cap(s.cTable) < maxSymbolValue+1 { + s.cTable = make([]cTableEntry, 0, maxSymbolValue+1) + } + + s.huffSort() + s.cTable = s.cTable[:s.symbolLen] + + var startNode = int16(s.symbolLen) + nonNullRank := s.symbolLen - 1 + + nodeNb := int16(startNode) + huffNode := s.nodes[1 : huffNodesLen+1] + + // This overlays the slice above, but allows "-1" index lookups. + // Different from reference implementation. + huffNode0 := s.nodes[0 : huffNodesLen+1] + + for huffNode[nonNullRank].count == 0 { + nonNullRank-- + } + + lowS := int16(nonNullRank) + nodeRoot := nodeNb + lowS - 1 + lowN := nodeNb + huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count + huffNode[lowS].parent, huffNode[lowS-1].parent = uint16(nodeNb), uint16(nodeNb) + nodeNb++ + lowS -= 2 + for n := nodeNb; n <= nodeRoot; n++ { + huffNode[n].count = 1 << 30 + } + // fake entry, strong barrier + huffNode0[0].count = 1 << 31 + + // create parents + for nodeNb <= nodeRoot { + var n1, n2 int16 + if huffNode0[lowS+1].count < huffNode0[lowN+1].count { + n1 = lowS + lowS-- + } else { + n1 = lowN + lowN++ + } + if huffNode0[lowS+1].count < huffNode0[lowN+1].count { + n2 = lowS + lowS-- + } else { + n2 = lowN + lowN++ + } + + huffNode[nodeNb].count = huffNode0[n1+1].count + huffNode0[n2+1].count + huffNode0[n1+1].parent, huffNode0[n2+1].parent = uint16(nodeNb), uint16(nodeNb) + nodeNb++ + } + + // distribute weights (unlimited tree height) + huffNode[nodeRoot].nbBits = 0 + for n := nodeRoot - 1; n >= startNode; n-- { + huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1 + } + for n := uint16(0); n <= nonNullRank; n++ { + huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1 + } + s.actualTableLog = s.setMaxHeight(int(nonNullRank)) + maxNbBits := s.actualTableLog + + // fill result into tree (val, nbBits) + if maxNbBits > tableLogMax { + return fmt.Errorf("internal error: maxNbBits (%d) > tableLogMax (%d)", maxNbBits, tableLogMax) + } + var nbPerRank [tableLogMax + 1]uint16 + var valPerRank [tableLogMax + 1]uint16 + for _, v := range huffNode[:nonNullRank+1] { + nbPerRank[v.nbBits]++ + } + // determine stating value per rank + { + min := uint16(0) + for n := maxNbBits; n > 0; n-- { + // get starting value within each rank + valPerRank[n] = min + min += nbPerRank[n] + min >>= 1 + } + } + + // push nbBits per symbol, symbol order + // TODO: changed `s.symbolLen` -> `nonNullRank+1` (micro-opt) + for _, v := range huffNode[:nonNullRank+1] { + s.cTable[v.symbol].nBits = v.nbBits + } + + // assign value within rank, symbol order + for n, val := range s.cTable[:s.symbolLen] { + v := valPerRank[val.nBits] + s.cTable[n].val = v + valPerRank[val.nBits] = v + 1 + } + + return nil +} + +// huffSort will sort symbols, decreasing order. +func (s *Scratch) huffSort() { + type rankPos struct { + base uint32 + current uint32 + } + + // Clear nodes + nodes := s.nodes[:huffNodesLen+1] + s.nodes = nodes + nodes = nodes[1 : huffNodesLen+1] + + // Sort into buckets based on length of symbol count. + var rank [32]rankPos + for _, v := range s.count[:s.symbolLen] { + r := highBit32(v+1) & 31 + rank[r].base++ + } + for n := 30; n > 0; n-- { + rank[n-1].base += rank[n].base + } + for n := range rank[:] { + rank[n].current = rank[n].base + } + for n, c := range s.count[:s.symbolLen] { + r := (highBit32(c+1) + 1) & 31 + pos := rank[r].current + rank[r].current++ + prev := nodes[(pos-1)&huffNodesMask] + for pos > rank[r].base && c > prev.count { + nodes[pos&huffNodesMask] = prev + pos-- + prev = nodes[(pos-1)&huffNodesMask] + } + nodes[pos&huffNodesMask] = nodeElt{count: c, symbol: byte(n)} + } + return +} + +func (s *Scratch) setMaxHeight(lastNonNull int) uint8 { + maxNbBits := s.TableLog + huffNode := s.nodes[1 : huffNodesLen+1] + //huffNode = huffNode[: huffNodesLen] + + largestBits := huffNode[lastNonNull].nbBits + + // early exit : no elt > maxNbBits + if largestBits <= maxNbBits { + return largestBits + } + totalCost := int(0) + baseCost := int(1) << (largestBits - maxNbBits) + n := uint32(lastNonNull) + + for huffNode[n].nbBits > maxNbBits { + totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)) + huffNode[n].nbBits = maxNbBits + n-- + } + // n stops at huffNode[n].nbBits <= maxNbBits + + for huffNode[n].nbBits == maxNbBits { + n-- + } + // n end at index of smallest symbol using < maxNbBits + + // renorm totalCost + totalCost >>= largestBits - maxNbBits /* note : totalCost is necessarily a multiple of baseCost */ + + /* repay normalized cost */ + { + const noSymbol = 0xF0F0F0F0 + var rankLast [tableLogMax + 2]uint32 + + for i := range rankLast[:] { + rankLast[i] = noSymbol + } + + // Get pos of last (smallest) symbol per rank + { + currentNbBits := uint8(maxNbBits) + for pos := int(n); pos >= 0; pos-- { + if huffNode[pos].nbBits >= currentNbBits { + continue + } + currentNbBits = huffNode[pos].nbBits /* < maxNbBits */ + rankLast[maxNbBits-currentNbBits] = uint32(pos) + } + } + + for totalCost > 0 { + nBitsToDecrease := uint8(highBit32(uint32(totalCost))) + 1 + + for ; nBitsToDecrease > 1; nBitsToDecrease-- { + highPos := rankLast[nBitsToDecrease] + lowPos := rankLast[nBitsToDecrease-1] + if highPos == noSymbol { + continue + } + if lowPos == noSymbol { + break + } + highTotal := huffNode[highPos].count + lowTotal := 2 * huffNode[lowPos].count + if highTotal <= lowTotal { + break + } + } + // only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) + // HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary + // FIXME: try to remove + for (nBitsToDecrease <= tableLogMax) && (rankLast[nBitsToDecrease] == noSymbol) { + nBitsToDecrease++ + } + totalCost -= 1 << (nBitsToDecrease - 1) + if rankLast[nBitsToDecrease-1] == noSymbol { + // this rank is no longer empty + rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease] + } + huffNode[rankLast[nBitsToDecrease]].nbBits++ + if rankLast[nBitsToDecrease] == 0 { + /* special case, reached largest symbol */ + rankLast[nBitsToDecrease] = noSymbol + } else { + rankLast[nBitsToDecrease]-- + if huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease { + rankLast[nBitsToDecrease] = noSymbol /* this rank is now empty */ + } + } + } + + for totalCost < 0 { /* Sometimes, cost correction overshoot */ + if rankLast[1] == noSymbol { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ + for huffNode[n].nbBits == maxNbBits { + n-- + } + huffNode[n+1].nbBits-- + rankLast[1] = n + 1 + totalCost++ + continue + } + huffNode[rankLast[1]+1].nbBits-- + rankLast[1]++ + totalCost++ + } + } + return maxNbBits +} + +type nodeElt struct { + count uint32 + parent uint16 + symbol byte + nbBits uint8 +} diff --git a/vendor/github.com/klauspost/compress/huff0/compress_test.go b/vendor/github.com/klauspost/compress/huff0/compress_test.go new file mode 100644 index 0000000..7cc3bb1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/compress_test.go @@ -0,0 +1,437 @@ +package huff0 + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/klauspost/compress/flate" +) + +type inputFn func() ([]byte, error) + +var testfiles = []struct { + name string + fn inputFn + err1X error + err4X error +}{ + // Digits is the digits of the irrational number e. Its decimal representation + // does not repeat, but there are only 10 possible digits, so it should be + // reasonably compressible. + {name: "digits", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/e.txt") }}, + // gettysburg.txt is a small plain text. + {name: "gettysburg", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/gettysburg.txt") }}, + // Twain is Project Gutenberg's edition of Mark Twain's classic English novel. + {name: "twain", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt") }}, + // Random bytes + {name: "random", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/sharnd.out") }, err1X: ErrIncompressible, err4X: ErrIncompressible}, + // Low entropy + {name: "low-ent.10k", fn: func() ([]byte, error) { return []byte(strings.Repeat("1221", 10000)), nil }}, + // Super Low entropy + {name: "superlow-ent-10k", fn: func() ([]byte, error) { return []byte(strings.Repeat("1", 10000) + strings.Repeat("2", 500)), nil }}, + // Zero bytes + {name: "zeroes", fn: func() ([]byte, error) { return make([]byte, 10000), nil }, err1X: ErrUseRLE, err4X: ErrUseRLE}, + {name: "crash1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash1.bin") }, err1X: ErrIncompressible, err4X: ErrIncompressible}, + {name: "crash2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash2.bin") }, err4X: ErrIncompressible}, + {name: "crash3", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash3.bin") }, err1X: ErrIncompressible, err4X: ErrIncompressible}, + {name: "endzerobits", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/endzerobits.bin") }, err1X: nil, err4X: ErrIncompressible}, + {name: "endnonzero", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/endnonzero.bin") }, err4X: ErrIncompressible}, + {name: "case1", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case1.bin") }, err1X: nil}, + {name: "case2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case2.bin") }, err1X: nil}, + {name: "case3", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/case3.bin") }, err1X: nil}, + {name: "pngdata.001", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/pngdata.bin") }, err1X: nil}, + {name: "normcount2", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/normcount2.bin") }, err1X: nil}, +} + +type fuzzInput struct { + name string + fn inputFn +} + +var testfilesExtended []fuzzInput + +func init() { + filepath.Walk("./fuzz/compress/corpus", func(path string, info os.FileInfo, err error) error { + if info.Size() == 0 || info.IsDir() { + return nil + } + testfilesExtended = append(testfilesExtended, fuzzInput{ + name: filepath.Base(path), + fn: func() ([]byte, error) { + return ioutil.ReadFile(path) + }, + }) + return nil + }) +} + +func TestCompress1X(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s Scratch + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress1X(buf0, &s) + if err != test.err1X { + t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) + } + if err != nil { + t.Log(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + min := s.minSize(len(buf0)) + if len(s.OutData) < min { + t.Errorf("output data length (%d) below shannon limit (%d)", len(s.OutData), min) + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + t.Logf("%s: %d -> %d bytes (%.2f:1) re:%t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + s.Out = nil + bRe, _, err := Compress1X(b, &s) + if err == nil { + t.Log("Could re-compress to", len(bRe)) + } + }) + } +} + +func TestCompress4X(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s Scratch + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress4X(buf0, &s) + if err != test.err4X { + t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err4X, err, err) + } + if err != nil { + t.Log(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + + t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + }) + } +} + +func TestCompress1XReuse(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s Scratch + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress1X(buf0, &s) + if err != test.err1X { + t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) + } + if err != nil { + t.Log(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + firstData := len(s.OutData) + s.Reuse = ReusePolicyAllow + b, re, err = Compress1X(buf0, &s) + if err != nil { + t.Errorf("got secondary error %v (%T)", err, err) + return + } + if !re { + t.Error("Didn't re-use even if data was the same") + } + if len(s.OutTable) != 0 { + t.Error("got table definition, don't want any") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + if len(b) != firstData { + t.Errorf("data length did not match first: %d, second:%d", firstData, len(b)) + } + t.Logf("%s: %d -> %d bytes (%.2f:1) %t", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re) + }) + } +} + +func BenchmarkDeflate(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + dec, err := flate.NewWriter(ioutil.Discard, flate.HuffmanOnly) + if err != nil { + b.Fatal(err) + } + if test.err1X != nil { + b.Skip("skipping") + } + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + dec.Reset(ioutil.Discard) + n, err := dec.Write(buf0) + if err != nil { + b.Fatal(err) + } + if n != len(buf0) { + b.Fatal("mismatch", n, len(buf0)) + } + dec.Close() + } + }) + } +} + +func BenchmarkCompress1XReuseNone(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyNone + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress1X(buf0, &s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress1X(buf0, &s) + if re { + b.Fatal("reused") + } + } + }) + } +} + +func BenchmarkCompress1XReuseAllow(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyAllow + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress1X(buf0, &s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress1X(buf0, &s) + if !re { + b.Fatal("not reused") + } + } + }) + } +} + +func BenchmarkCompress1XReusePrefer(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyPrefer + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress1X(buf0, &s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress1X(buf0, &s) + if !re { + b.Fatal("not reused") + } + } + }) + } +} + +func BenchmarkCompress4XReuseNone(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err4X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyNone + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress4X(buf0, &s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress4X(buf0, &s) + if re { + b.Fatal("reused") + } + } + }) + } +} + +func BenchmarkCompress4XReuseAllow(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err4X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyAllow + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress4X(buf0, &s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress4X(buf0, &s) + if !re { + b.Fatal("not reused") + } + } + }) + } +} + +func BenchmarkCompress4XReusePrefer(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err4X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s Scratch + s.Reuse = ReusePolicyPrefer + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + _, re, err := Compress4X(buf0, &s) + if err != test.err4X { + b.Fatal("unexpected error:", err) + } + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, re, _ = Compress4X(buf0, &s) + if !re { + b.Fatal("not reused") + } + } + }) + } +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go new file mode 100644 index 0000000..436cc41 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -0,0 +1,392 @@ +package huff0 + +import ( + "errors" + "fmt" + "io" + + "github.com/klauspost/compress/fse" +) + +type dTable struct { + single []dEntrySingle + double []dEntryDouble +} + +// single-symbols decoding +type dEntrySingle struct { + byte uint8 + nBits uint8 +} + +// double-symbols decoding +type dEntryDouble struct { + seq uint16 + nBits uint8 + len uint8 +} + +// ReadTable will read a table from the input. +// The size of the input may be larger than the table definition. +// Any content remaining after the table definition will be returned. +// if no Scratch is provided a new one is allocated. +// The returned Scratch can be used for decoding input using this table. +func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) { + s, err = s.prepare(in) + if err != nil { + return s, nil, err + } + if len(in) <= 1 { + return s, nil, errors.New("input too small for table") + } + iSize := in[0] + in = in[1:] + if iSize >= 128 { + // Uncompressed + oSize := iSize - 127 + iSize = (oSize + 1) / 2 + if int(iSize) > len(in) { + return s, nil, errors.New("input too small for table") + } + for n := uint8(0); n < oSize; n += 2 { + v := in[n/2] + s.huffWeight[n] = v >> 4 + s.huffWeight[n+1] = v & 15 + } + s.symbolLen = uint16(oSize) + in = in[iSize:] + } else { + if len(in) <= int(iSize) { + return s, nil, errors.New("input too small for table") + } + // FSE compressed weights + s.fse.DecompressLimit = 255 + hw := s.huffWeight[:] + s.fse.Out = hw + b, err := fse.Decompress(in[:iSize], s.fse) + s.fse.Out = nil + if err != nil { + return s, nil, err + } + if len(b) > 255 { + return s, nil, errors.New("corrupt input: output table too large") + } + s.symbolLen = uint16(len(b)) + in = in[iSize:] + } + + // collect weight stats + var rankStats [tableLogMax + 1]uint32 + weightTotal := uint32(0) + for _, v := range s.huffWeight[:s.symbolLen] { + if v > tableLogMax { + return s, nil, errors.New("corrupt input: weight too large") + } + rankStats[v]++ + weightTotal += (1 << (v & 15)) >> 1 + } + if weightTotal == 0 { + return s, nil, errors.New("corrupt input: weights zero") + } + + // get last non-null symbol weight (implied, total must be 2^n) + { + tableLog := highBit32(weightTotal) + 1 + if tableLog > tableLogMax { + return s, nil, errors.New("corrupt input: tableLog too big") + } + s.actualTableLog = uint8(tableLog) + // determine last weight + { + total := uint32(1) << tableLog + rest := total - weightTotal + verif := uint32(1) << highBit32(rest) + lastWeight := highBit32(rest) + 1 + if verif != rest { + // last value must be a clean power of 2 + return s, nil, errors.New("corrupt input: last value not power of two") + } + s.huffWeight[s.symbolLen] = uint8(lastWeight) + s.symbolLen++ + rankStats[lastWeight]++ + } + } + + if (rankStats[1] < 2) || (rankStats[1]&1 != 0) { + // by construction : at least 2 elts of rank 1, must be even + return s, nil, errors.New("corrupt input: min elt size, even check failed ") + } + + // TODO: Choose between single/double symbol decoding + + // Calculate starting value for each rank + { + var nextRankStart uint32 + for n := uint8(1); n < s.actualTableLog+1; n++ { + current := nextRankStart + nextRankStart += rankStats[n] << (n - 1) + rankStats[n] = current + } + } + + // fill DTable (always full size) + tSize := 1 << tableLogMax + if len(s.dt.single) != tSize { + s.dt.single = make([]dEntrySingle, tSize) + } + + for n, w := range s.huffWeight[:s.symbolLen] { + length := (uint32(1) << w) >> 1 + d := dEntrySingle{ + byte: uint8(n), + nBits: s.actualTableLog + 1 - w, + } + for u := rankStats[w]; u < rankStats[w]+length; u++ { + s.dt.single[u] = d + } + rankStats[w] += length + } + return s, in, nil +} + +// Decompress1X will decompress a 1X encoded stream. +// The supplied input must match the end of a block exactly. +// Before this is called, the table must be initialized with ReadTable. +func (s *Scratch) Decompress1X(in []byte) (out []byte, err error) { + if len(s.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + var br bitReader + err = br.init(in) + if err != nil { + return nil, err + } + s.Out = s.Out[:0] + + decode := func() byte { + val := br.peekBitsFast(s.actualTableLog) /* note : actualTableLog >= 1 */ + v := s.dt.single[val] + br.bitsRead += v.nBits + return v.byte + } + hasDec := func(v dEntrySingle) byte { + br.bitsRead += v.nBits + return v.byte + } + + // Avoid bounds check by always having full sized table. + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + dt := s.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + var tmp = s.huffWeight[:256] + var off uint8 + + for br.off >= 8 { + br.fillFast() + tmp[off+0] = hasDec(dt[br.peekBitsFast(s.actualTableLog)&tlMask]) + tmp[off+1] = hasDec(dt[br.peekBitsFast(s.actualTableLog)&tlMask]) + br.fillFast() + tmp[off+2] = hasDec(dt[br.peekBitsFast(s.actualTableLog)&tlMask]) + tmp[off+3] = hasDec(dt[br.peekBitsFast(s.actualTableLog)&tlMask]) + off += 4 + if off == 0 { + s.Out = append(s.Out, tmp...) + } + } + + s.Out = append(s.Out, tmp[:off]...) + + for !br.finished() { + br.fill() + s.Out = append(s.Out, decode()) + } + return s.Out, br.close() +} + +// Decompress4X will decompress a 4X encoded stream. +// Before this is called, the table must be initialized with ReadTable. +// The supplied input must match the end of a block exactly. +// The destination size of the uncompressed data must be known and provided. +func (s *Scratch) Decompress4X(in []byte, dstSize int) (out []byte, err error) { + if len(s.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if len(in) < 6+(4*1) { + return nil, errors.New("input too small") + } + // TODO: We do not detect when we overrun a buffer, except if the last one does. + + var br [4]bitReader + start := 6 + for i := 0; i < 3; i++ { + length := int(in[i*2]) | (int(in[i*2+1]) << 8) + if start+length >= len(in) { + return nil, errors.New("truncated input (or invalid offset)") + } + err = br[i].init(in[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err = br[3].init(in[start:]) + if err != nil { + return nil, err + } + + // Prepare output + if cap(s.Out) < dstSize { + s.Out = make([]byte, 0, dstSize) + } + s.Out = s.Out[:dstSize] + // destination, offset to match first output + dstOut := s.Out + dstEvery := (dstSize + 3) / 4 + + decode := func(br *bitReader) byte { + val := br.peekBitsFast(s.actualTableLog) /* note : actualTableLog >= 1 */ + v := s.dt.single[val] + br.bitsRead += v.nBits + return v.byte + } + + // Use temp table to avoid bound checks/append penalty. + var tmp = s.huffWeight[:256] + var off uint8 + + // Decode 2 values from each decoder/loop. + const bufoff = 256 / 4 +bigloop: + for { + for i := range br { + if br[i].off < 4 { + break bigloop + } + br[i].fillFast() + } + tmp[off] = decode(&br[0]) + tmp[off+bufoff] = decode(&br[1]) + tmp[off+bufoff*2] = decode(&br[2]) + tmp[off+bufoff*3] = decode(&br[3]) + tmp[off+1] = decode(&br[0]) + tmp[off+1+bufoff] = decode(&br[1]) + tmp[off+1+bufoff*2] = decode(&br[2]) + tmp[off+1+bufoff*3] = decode(&br[3]) + off += 2 + if off == bufoff { + copy(dstOut, tmp[:bufoff]) + copy(dstOut[dstEvery:], tmp[bufoff:bufoff*2]) + copy(dstOut[dstEvery*2:], tmp[bufoff*2:bufoff*3]) + copy(dstOut[dstEvery*3:], tmp[bufoff*3:bufoff*4]) + off = 0 + dstOut = dstOut[bufoff:] + // There must at least be 3 buffers left. + if len(dstOut) < dstEvery*3+3 { + return nil, errors.New("corruption detected: stream overrun") + } + } + } + if off > 0 { + ioff := int(off) + if len(dstOut) < dstEvery*3-ioff { + return nil, errors.New("corruption detected: stream overrun") + } + copy(dstOut, tmp[:off]) + copy(dstOut[dstEvery:dstEvery+ioff], tmp[bufoff:bufoff*2]) + copy(dstOut[dstEvery*2:dstEvery*2+ioff], tmp[bufoff*2:bufoff*3]) + copy(dstOut[dstEvery*3:dstEvery*3+ioff], tmp[bufoff*3:bufoff*4]) + dstOut = dstOut[off:] + } + + for i := range br { + offset := dstEvery * i + br := &br[i] + for !br.finished() { + br.fill() + if offset >= len(dstOut) { + return nil, errors.New("corruption detected: stream overrun") + } + dstOut[offset] = decode(br) + offset++ + } + err = br.close() + if err != nil { + return nil, err + } + } + + return s.Out, nil +} + +// matches will compare a decoding table to a coding table. +// Errors are written to the writer. +// Nothing will be written if table is ok. +func (s *Scratch) matches(ct cTable, w io.Writer) { + if s == nil || len(s.dt.single) == 0 { + return + } + dt := s.dt.single[:1< 0 { + fmt.Fprintf(w, "%d errros in base, stopping\n", errs) + continue + } + // Ensure that all combinations are covered. + for i := uint16(0); i < (1 << ub); i++ { + vval := top | i + dec := dt[vval] + if dec.nBits != enc.nBits { + fmt.Fprintf(w, "symbol 0x%x bit size mismatch (enc: %d, dec:%d).\n", vval, enc.nBits, dec.nBits) + errs++ + } + if dec.byte != uint8(sym) { + fmt.Fprintf(w, "symbol 0x%x decoder output mismatch (enc: %d, dec:%d).\n", vval, sym, dec.byte) + errs++ + } + if errs > 20 { + fmt.Fprintf(w, "%d errros, stopping\n", errs) + break + } + } + if errs == 0 { + ok++ + broken-- + } + } + if broken > 0 { + fmt.Fprintf(w, "%d broken, %d ok\n", broken, ok) + } +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_test.go b/vendor/github.com/klauspost/compress/huff0/decompress_test.go new file mode 100644 index 0000000..579ab39 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_test.go @@ -0,0 +1,482 @@ +package huff0 + +import ( + "bytes" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestDecompress1X(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s = &Scratch{} + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress1X(buf0, s) + if err != test.err1X { + t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) + } + if err != nil { + t.Log(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + + wantRemain := len(s.OutData) + t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + + s.Out = nil + var remain []byte + s, remain, err = ReadTable(b, s) + if err != nil { + t.Error(err) + return + } + var buf bytes.Buffer + if s.matches(s.prevTable, &buf); buf.Len() > 0 { + t.Error(buf.String()) + } + if len(remain) != wantRemain { + t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) + } + t.Logf("remain: %d bytes, ok", len(remain)) + dc, err := s.Decompress1X(remain) + if err != nil { + t.Error(err) + return + } + if len(buf0) != len(dc) { + t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) + if len(buf0) > len(dc) { + buf0 = buf0[:len(dc)] + } else { + dc = dc[:len(buf0)] + } + if !cmp.Equal(buf0, dc) { + if len(dc) > 1024 { + t.Log(string(dc[:1024])) + t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) + } else { + t.Log(string(dc)) + t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) + } + } + return + } + if !cmp.Equal(buf0, dc) { + if len(buf0) > 1024 { + t.Log(string(dc[:1024])) + } else { + t.Log(string(dc)) + } + //t.Errorf(test.name+": decompressed, got delta: \n%s") + t.Errorf(test.name + ": decompressed, got delta") + } + if !t.Failed() { + t.Log("... roundtrip ok!") + } + }) + } +} + +func TestDecompress4X(t *testing.T) { + for _, test := range testfiles { + t.Run(test.name, func(t *testing.T) { + var s = &Scratch{} + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress4X(buf0, s) + if err != test.err4X { + t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) + } + if err != nil { + t.Log(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + + wantRemain := len(s.OutData) + t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + + s.Out = nil + var remain []byte + s, remain, err = ReadTable(b, s) + if err != nil { + t.Error(err) + return + } + var buf bytes.Buffer + if s.matches(s.prevTable, &buf); buf.Len() > 0 { + t.Error(buf.String()) + } + if len(remain) != wantRemain { + t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) + } + t.Logf("remain: %d bytes, ok", len(remain)) + dc, err := s.Decompress4X(remain, len(buf0)) + if err != nil { + t.Error(err) + return + } + if len(buf0) != len(dc) { + t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) + if len(buf0) > len(dc) { + buf0 = buf0[:len(dc)] + } else { + dc = dc[:len(buf0)] + } + if !cmp.Equal(buf0, dc) { + if len(dc) > 1024 { + t.Log(string(dc[:1024])) + t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) + } else { + t.Log(string(dc)) + t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) + } + } + return + } + if !cmp.Equal(buf0, dc) { + if len(buf0) > 1024 { + t.Log(string(dc[:1024])) + } else { + t.Log(string(dc)) + } + //t.Errorf(test.name+": decompressed, got delta: \n%s") + t.Errorf(test.name + ": decompressed, got delta") + } + if !t.Failed() { + t.Log("... roundtrip ok!") + } + }) + } +} + +func TestDecompress1XFuzz(t *testing.T) { + for _, test := range testfilesExtended { + t.Run(test.name, func(t *testing.T) { + var s = &Scratch{} + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress1X(buf0, s) + if err != nil { + if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig { + t.Log(test.name, err.Error()) + return + } + t.Error(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + + wantRemain := len(s.OutData) + t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + + s.Out = nil + var remain []byte + s, remain, err = ReadTable(b, s) + if err != nil { + t.Error(err) + return + } + var buf bytes.Buffer + if s.matches(s.prevTable, &buf); buf.Len() > 0 { + t.Error(buf.String()) + } + if len(remain) != wantRemain { + t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) + } + t.Logf("remain: %d bytes, ok", len(remain)) + dc, err := s.Decompress1X(remain) + if err != nil { + t.Error(err) + return + } + if len(buf0) != len(dc) { + t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) + if len(buf0) > len(dc) { + buf0 = buf0[:len(dc)] + } else { + dc = dc[:len(buf0)] + } + if !cmp.Equal(buf0, dc) { + if len(dc) > 1024 { + t.Log(string(dc[:1024])) + t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) + } else { + t.Log(string(dc)) + t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) + } + } + return + } + if !cmp.Equal(buf0, dc) { + if len(buf0) > 1024 { + t.Log(string(dc[:1024])) + } else { + t.Log(string(dc)) + } + //t.Errorf(test.name+": decompressed, got delta: \n%s") + t.Errorf(test.name + ": decompressed, got delta") + } + if !t.Failed() { + t.Log("... roundtrip ok!") + } + }) + } +} + +func TestDecompress4XFuzz(t *testing.T) { + for _, test := range testfilesExtended { + t.Run(test.name, func(t *testing.T) { + var s = &Scratch{} + buf0, err := test.fn() + if err != nil { + t.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + b, re, err := Compress4X(buf0, s) + if err != nil { + if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig { + t.Log(test.name, err.Error()) + return + } + t.Error(test.name, err.Error()) + return + } + if b == nil { + t.Error("got no output") + return + } + if len(s.OutTable) == 0 { + t.Error("got no table definition") + } + if re { + t.Error("claimed to have re-used.") + } + if len(s.OutData) == 0 { + t.Error("got no data output") + } + + wantRemain := len(s.OutData) + t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) + + s.Out = nil + var remain []byte + s, remain, err = ReadTable(b, s) + if err != nil { + t.Error(err) + return + } + var buf bytes.Buffer + if s.matches(s.prevTable, &buf); buf.Len() > 0 { + t.Error(buf.String()) + } + if len(remain) != wantRemain { + t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) + } + t.Logf("remain: %d bytes, ok", len(remain)) + dc, err := s.Decompress4X(remain, len(buf0)) + if err != nil { + t.Error(err) + return + } + if len(buf0) != len(dc) { + t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) + if len(buf0) > len(dc) { + buf0 = buf0[:len(dc)] + } else { + dc = dc[:len(buf0)] + } + if !cmp.Equal(buf0, dc) { + if len(dc) > 1024 { + t.Log(string(dc[:1024])) + t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) + } else { + t.Log(string(dc)) + t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) + } + } + return + } + if !cmp.Equal(buf0, dc) { + if len(buf0) > 1024 { + t.Log(string(dc[:1024])) + } else { + t.Log(string(dc)) + } + //t.Errorf(test.name+": decompressed, got delta: \n%s") + t.Errorf(test.name + ": decompressed, got delta") + } + if !t.Failed() { + t.Log("... roundtrip ok!") + } + }) + } +} + +func BenchmarkDecompress1XTable(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s = &Scratch{} + s.Reuse = ReusePolicyNone + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + compressed, _, err := Compress1X(buf0, s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + s.Out = nil + s, remain, _ := ReadTable(compressed, s) + s.Decompress1X(remain) + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + s, remain, err := ReadTable(compressed, s) + if err != nil { + b.Fatal(err) + } + _, err = s.Decompress1X(remain) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + +func BenchmarkDecompress1XNoTable(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err1X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s = &Scratch{} + s.Reuse = ReusePolicyNone + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + compressed, _, err := Compress1X(buf0, s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + s.Out = nil + s, remain, _ := ReadTable(compressed, s) + s.Decompress1X(remain) + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, err = s.Decompress1X(remain) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + +func BenchmarkDecompress4XNoTable(b *testing.B) { + for _, tt := range testfiles { + test := tt + if test.err4X != nil { + continue + } + b.Run(test.name, func(b *testing.B) { + var s = &Scratch{} + s.Reuse = ReusePolicyNone + buf0, err := test.fn() + if err != nil { + b.Fatal(err) + } + if len(buf0) > BlockSizeMax { + buf0 = buf0[:BlockSizeMax] + } + compressed, _, err := Compress4X(buf0, s) + if err != test.err1X { + b.Fatal("unexpected error:", err) + } + s.Out = nil + s, remain, _ := ReadTable(compressed, s) + s.Decompress4X(remain, len(buf0)) + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(buf0))) + for i := 0; i < b.N; i++ { + _, err = s.Decompress4X(remain, len(buf0)) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/01ace8efdfd46d82b0fef511b259933ced9d13ec-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/01ace8efdfd46d82b0fef511b259933ced9d13ec-2 new file mode 100644 index 0000000..69291ec --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/01ace8efdfd46d82b0fef511b259933ced9d13ec-2 @@ -0,0 +1 @@ +012939495969798997C2 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/049f4a878ab48c404bd0950e2366e3c0eaad4318-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/049f4a878ab48c404bd0950e2366e3c0eaad4318-3 new file mode 100644 index 0000000000000000000000000000000000000000..84e824506e3f511550eab10b677551829223aca1 GIT binary patch literal 41 xcmaFAe=j!!lbNBJfsy6zsT+6BsF%8EVW^bk?Lh4mbb+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 new file mode 100644 index 0000000000000000000000000000000000000000..3494057c2ee107c202560c0ba1de1cd11149e283 GIT binary patch literal 1647 zcmcIkYmd`b5G^19ZBYbBNClOuf)D-BI$Ym}AJS6l8#^Jd&HKqpgB{y>zc+~!A@R#s z>Nr_;fqt&!+(hGus*q%8uuqdmjh;)%NuJ?Dyy6ZY96V zBGh3tY38iah&nK4;s@-?p*&J`&ZAy6Oth3on51r~LxBc@;cRr{r%9pc6xxShW z+tp4>XQEzT8s z{3fU@;x4htV~_paqp;b{#0(ah@@0R9=Pe6>OKcaWnJ%8CK0veB--Xza%a~<_k_wYD z6Ppt(8JVUu-B1cwNxUVIjurJ4Lp`9XEdeEgX&Uh;#w}CmU`0n*nT8TMBGdlPByq2Z zNigHcBl0D6rEN)HXGESDg+b4=HR<=hOE!t|U4%rwcUx}|+4~B?&^YybaS0dvt2-IW z%b6Z1aRXcz{7i98g+v}pTY<^+w9tdJCoxM`xuzv~Y^c?Gd+6rSQqA4G11>C5ZfN&3 z&Z96zlQ@*f_S0@aA}b`q@|`pfXo{GD@LeS=g)4Wx7C>JqpglZ=;`s8PTgU1CtxC-Z)8STLlZY6RTQEMG%wKv z0>)xfP186^MYxV%R3#WuQCv#U>o^;(Q;tPkLvA!?itmNWsh;>?BGJm~og z_M5ge{)I0`u$%c~@qOjdL(dD7*L#uvb}^uOa&v5E^zvyr(8Sl<;Yk^K(liA=!jrC) zxV5+|9+&jwGu)SWNXhjA27pW_Ek#kFak%rpkYP!*USQfLm!{*mAvYYm*OS~6woA^G zbP6(Um;=wX>@C0ozytz3Q>@j%7sR8AK@7n-3Qu)hO@Z>Ont5w_bbb8qd9r;f_Puj! z{Dg!yEA^nJ)mmGaNYaMUvIWZt@GXM_(f2e1a}`x=>jMqykbylgFnW3s%w0HxLLC?i Qd&ztgHX|t8paf6<1rmDMxc~qF literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc new file mode 100644 index 0000000..80da8c0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc @@ -0,0 +1 @@ +CaDCaDcAecDc7De7777-accD77DeDEEAf_ZohDnpPnXJKmFtxmGZFOVgbxbCaAEEAAfecbD4dc44.x.xAfF-45405050xdbCaDAEEd0EcdDA7AfecbD4dc454057025Vz-04454224054e-0276666767011776664.efZohQpggnpGPTrniXRqJlKmFtmGZFOgVMgwxAAfeB643xbBCaBABE3BEcd3AAfecbD64Bdc664423703235e-07503-0xB66C9fad.-75946554523692857652911-i1V___hoNaqWTStRM9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031259101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125\B___L7D3PS0hd1_Gxkg_Eg2P_Uo_3yd3gU_a_2__Ct28_l1w16r4_p_Q898Fv_22_6_28282357FECfCFCdBEEaE47fb5Bc{1.0xd-0534420.-8911368683772161602973534420.-89113686<-7301351713.7376291319585350 [ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 new file mode 100644 index 0000000000000000000000000000000000000000..9e7e94e292902cbfa51598545670e74c4d5a411e GIT binary patch literal 1919 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/26ccc59f9c4d89063210f2e8ddd0c26394c2a607-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/26ccc59f9c4d89063210f2e8ddd0c26394c2a607-2 new file mode 100644 index 0000000..20debe4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/26ccc59f9c4d89063210f2e8ddd0c26394c2a607-2 @@ -0,0 +1 @@ +012756789aefxbcdefx \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/287d18afe5e0d54d4554a39aa2acff99d696136d b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/287d18afe5e0d54d4554a39aa2acff99d696136d new file mode 100644 index 0000000..299c56c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/287d18afe5e0d54d4554a39aa2acff99d696136d @@ -0,0 +1 @@ +8869-0x0e.-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-70989128513186264514923095703125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/29e95908e0f3e9f3e189441de6ed797b7bee2449-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/29e95908e0f3e9f3e189441de6ed797b7bee2449-2 new file mode 100644 index 0000000..16749a6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/29e95908e0f3e9f3e189441de6ed797b7bee2449-2 @@ -0,0 +1 @@ +0345678defghijklmnopqrstuvwxyz18872161F029739CFeBEbaE7fb-05340.-13686 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2c93d4381a547aa7001acfffcf51dc323a0cdf2b-10 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2c93d4381a547aa7001acfffcf51dc323a0cdf2b-10 new file mode 100644 index 0000000000000000000000000000000000000000..02700fd0782fcb3a2096d6167c3459c66a77910f GIT binary patch literal 67 icmZQ%U<5-JMixd0i;)2+0OW#1pppmyup*!YG6Vn%iU4T< literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e0d10ca05bdebe3fe84c481004adb11a1cc761c-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e0d10ca05bdebe3fe84c481004adb11a1cc761c-2 new file mode 100644 index 0000000000000000000000000000000000000000..001954fdd732318a5c451b2cd9a2664ad6829d98 GIT binary patch literal 1700 zcmcJP*^k>c5Qm!v$k7%?`cR+=8lXtuib$bI>H;=xBw610TAz}SEWlXS;ZwdXSqPB7 ze1Q(--K1$=`p^mjB@SnXL-PCa$7k2izJL6oHlM$rf1JN{oQE~%`j^`DkNKai?)2XL z)o(A~ym<0q({g&X)^yXYO~3j0^Q(*6)r%(^@VxGIr?soY;oFVlT(w%W!`1Weoa$`W z8r<~C^TFxJ+lyc4t!mkEX1&vH*It!7wL_z`Pm)2Q(4DsT%cQm5ubbWNw7seBmyLQ- zcnzI?dsA6dm$|_(j7hV<-Bps+V4WI4(Ae&FH$SDmH8O19_6;NOHJNvRH*DM2a*GBg zf@DOnOb8|j5tLdZ+cu0a0IQ77;kK_5Wc$QW!G0T~@*pG=8ACiG1Yx9Ngs{Rtn8>n< z1*BjZ!wXg!t4LG$7v?+1LT(JT@#Na)>7RPhqc{@PwwW%Ys9pg{eJkn#3eV z=uz|RuVbR0mx6Sinz}s-sb-JICiUbI68elXcyxvsz3gV`H_>l8|*7 z+q0K%9xpB|YZ5Q^_04HgXq@`hN&QfbqxcjphNVVSkDd;Pak&FWJ&O;AS>-4Q1tEK9 z-4uef^gOkK)G`7g6@|1ESXRlu5&TsUyH2Uvp4E@D_Hn@2k+BLC@!-+@o5`u!-yO4T zSn2f2?g|F)zn`48$7~4w)xfeY#HaINtNJzp(z4ki>YbXqZ?n(k_`-al*)g<-rZ zyPaARKv7q-cyKr@vq2k569rL(>H;?lN}@YlOH`m(u?VraYD_{?Hy&-ZwFIb^KF z8WCe|JxW5cz(#iHX5CXQX47QLmh}P4*sjcW-2GZi0~=1u9u*4gjyTR|7!-jv;${r! zOnnb{DRN*4&|4&Y+~W?Ilae#+W&)OSE+wo2ovJ1xqG^PvNcc>5G3VGTsvJblxM!X7 za>~a%Gv|B^xlMnZ3nT|tKtz>^0hA)!2~OWD@T$=0ZAHCC5#9_E-3_hU{a)9 z0$>LAp{T+;3H-PaB;Xb4yaaIJMVPQWvuK#Nijd4NYf+$>+erHN&-Y~c$;4}cquaCw9S$SMn@XDS!I%_Hy6$T0BlH&CdG0imvlDborAiPGY3Mso= zN{JTpxs>x{OFkQhA!@(^nQf$;2#uM*1d8Cttz&H*B~-uN3@S@stm)ru2ff>me+J+C xU$PPrrNuxm<~PgvYAK%Ymf{Fq2z*YK-$Vc5N`U;YE+`4u(nZR(zWpTj`Cmlp=#>Bf literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e85ccbaa127cbf77bb8f0b5c3afdcf53f63f2d8-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e85ccbaa127cbf77bb8f0b5c3afdcf53f63f2d8-2 new file mode 100644 index 0000000..e7c19ad --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/2e85ccbaa127cbf77bb8f0b5c3afdcf53f63f2d8-2 @@ -0,0 +1 @@ +"4656612873077392578125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/30632e96a06600a75b47b4cbe0db74b959d09aa5 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/30632e96a06600a75b47b4cbe0db74b959d09aa5 new file mode 100644 index 0000000000000000000000000000000000000000..4529b55e3b6911d6b439b8b7fa375747e418303b GIT binary patch literal 553 zcmZvW?N8cJ6vkDYF`{PCnJJrY&X~%F(Vy=7t9dMzMe>39(;emE}| zQcOS!laY)WV+1RK2qd8hN!tmG@V^j>!x)sH424;UUlN<^Je6uPNky2aoTe_Zh8}*^ zbpCtu(0RbVL}$#NU@w8_j69Q4Z=A(bnL~*w;FSS*VG2HE6AFwaxlD2m00b&jASv9z z;bQmT%aN|>jv~Lq`Fd}NtLCkFZMV+%HwS~CPkk?6H>-v%y2i|EJLW9wbWO|38ouTE zJ@OdKmInX; literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/308f53f64ce26d56e4379931ff3611a7dd49325f-10 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/308f53f64ce26d56e4379931ff3611a7dd49325f-10 new file mode 100644 index 0000000000000000000000000000000000000000..ec62c5ce57b6554a2286d417ab670e96af45e6db GIT binary patch literal 64 hcmZQ%U<5-JMixd0i;)2+0OW#1Kui!sh=4?qApi<=0A>IH literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/31e020e2f79260ddcbf377c8e1256288b57d32b8-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/31e020e2f79260ddcbf377c8e1256288b57d32b8-1 new file mode 100644 index 0000000..2e05aff --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/31e020e2f79260ddcbf377c8e1256288b57d32b8-1 @@ -0,0 +1 @@ +186264514923095703125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/32a3cf4aef238d77278831c3744c1327dcc8f8c0-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/32a3cf4aef238d77278831c3744c1327dcc8f8c0-3 new file mode 100644 index 0000000000000000000000000000000000000000..aa7650d5edefc154986e199c8ba41b90830ed110 GIT binary patch literal 3 KcmZQ#U;qFB2>=5C literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/350b061ff78cfb97b28716ec96e27f616d439f97-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/350b061ff78cfb97b28716ec96e27f616d439f97-1 new file mode 100644 index 0000000000000000000000000000000000000000..a502d68ede6c23ab30803e35856d4d9712027b2c GIT binary patch literal 302 zcmait%WA?v7)E^p*Y11*W$wu==g&+6N@*>UmTZ196ODqGSON`wiav5RBHbu%zmIc{ z_hySUI(zZS{+1v8#u>E{jr`c}4Pg_JZ-99T2Q+%xv^B1hYmC{;vJ}JQf2W}#> zUU?;;QcMXcG~-%EgfltOlu*S+Leld(9(??A(qEKG(p4T3R)RI)Tov({P;jBLS6}cp tz9<8Yd+SB;5A!MM>`GfLKs#5iMeJ+{AiT6C8TQ$G*n{S+^Q4*o`~hyQP*VT^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3542214eb977ea9bdabcc55601d7876b6227b501-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3542214eb977ea9bdabcc55601d7876b6227b501-2 new file mode 100644 index 0000000000000000000000000000000000000000..800763fc7a221e9856104550b7e5a0c25bb5a85b GIT binary patch literal 506 zcmXv~+iu!G5Y45jqFzwdhpLLyzVxB0THM{)UGG||)Ox`{A%shS5MD;uYZDS6KuqJ% z>!)|Ev`3@S8I9(gqxtya!Q&5K4u0%E`TfV@@Y7NM*FFFk7hGGGm^kMT@{j^t-2sc-lF^{?kHd*=^YAKO9R|mrmhsy2d7c#hZNb zwy-_wt*6~py^+mFh%HpuRFhkkX|0t`;!tU$T+RW~O*(`HzS>g`0L@`jamqa)o+K1V zWFi{gTN|MbN>A|8Ez=(_y* z?p|>;zo7$p-b#<1;(KTJBwY!r28=9EMXW1WBSKOe#{pWOZ!kY-eYS2%M%)owq5QCj82~ZQd~FwEpz>% literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3b1d88a86a30b301e5f509a756f43ef34fad55b0-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3b1d88a86a30b301e5f509a756f43ef34fad55b0-2 new file mode 100644 index 0000000000000000000000000000000000000000..edf320c82b1a51edfcb49add1ab577678723c72d GIT binary patch literal 1055 zcmcIi+fLg+5N$<8sai#?)EAKY(!SQ#UcI(NrDkI%1QH;35|9>ei~|X|lf<$3b)?P) zTG2jMtz}ueo|!Xq=9~|E7dv~Uk1t-m{c>FTdjI{+=lb;h{j|~8EuAbD=ebY0hf(9G zKWLRJ2mQ)YZErnXua~vfpsm!_<>pu%jNAVHt~KaXjt+{AM*p_8zM1#V=HuJfR<&bw zM&n|wv|60hj{BqbVv)A1{lleYB^gU4I!cqg)^@WqzOLjar+2;4*8jLG3J8HgkAJA!G#RMX*0D5rjP@P0=~kv z5p`Wk1+pkY6eYPZ2z+5M1s8}uqHVwgMbM3ktO)`hr%;ao%tBOf>NvzfLQskv><~&E zN-3e3+ZMtu5||+BaDp8QH~8hiIE26$h&X1L%sGZUz<>)yobjxG%1Fd20>m5gKNJuBX}-tA}|gE$3HXOf>3Hu@Bv3G_>!!tVk}8Effz9A2(v zC?%CNn~gP-gmKfv<7PZ+C!WWo7sf2;b|uq1w5)F^5g=N9#u#UIFY%+wlu9Dyk)PqB_Ox$j7#k{9g{7J|t``6oe`Cm|}jS~OL^UW5FLzx@+kDKsA sv~QW73Pk;Dg?)Ow-O`tyLWS0AwvDhX4Qo literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 new file mode 100644 index 0000000000000000000000000000000000000000..7da12c9097a8e5a60d74c2fd3f55eab67eba32fd GIT binary patch literal 16 UcmWe+;$Z*+Mn)iJU}Rwi00IgCD*ylh literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/40b8de701a171fddefdc4459023121a1e605b16c b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/40b8de701a171fddefdc4459023121a1e605b16c new file mode 100644 index 0000000..ac5355d --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/40b8de701a171fddefdc4459023121a1e605b16c @@ -0,0 +1 @@ +0aaef11119910xC8fFCFCEEaEfb.144-0440.-89116868771616097937988815-9101862645149230957031250xbCaBEBEDAfebDBdc32-xcA3.7475562603-0x0e0862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125|7318e000175420 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 new file mode 100644 index 0000000000000000000000000000000000000000..bf6dcb36149a8efffb81bcf92ff09ce1c7aebe98 GIT binary patch literal 1089 zcmXw1i&EQ06vYszd4!U5NGUBeDU%_LEoFBl?XD;-NHP-f+r~D=opx(kk}-aR47Pyq zU;Tl8m1nwg(w))0cW008>zr@@c>nWT#?My0Zmd0je%g6?{paJ#%G%DsQf%>Y?Rk=$ z=RdrT%*S@4(eQmbjUIj8n_GO^ig3vK!OGI){8PJsczEz` z{zJOKk$=Y`S+8#uEi>nN_U>-f`vJl|RG7gOsKb0rAu zcs#h^c4pG?<+NcKOE<0JFxAZ+9lT3t8;LNv7!xDe;jz^>2Uc@nm2P?=#O(57%_c7= zn&NIWV>L>pR#5Z2=Mr)JoUb@}C%6B@Wi+28Q zL?xI;YyDhy6!O5zg_-+mUd{aW z%#KHf!I%gD7#qORG?zLQhd0fjPWp1x1>n?k?L=d2*Au6w4mfQ%3F5g8JK;1aAmBum z0HH1*4|C$J`;2 zWg-zu2<81jND+aB!GLG3h3Q2m_F6Y##P)SAlWK98Om#VPjOmO~R>{yN)pecfF4cKX zM3C=StEi{a9}!X^#0bk!R*|X@2_gmPNY{x(fi4k^ubpC9hcpE7K2#*}Z4nRxrHTN? zgmZN5c9f1JB@y!&>oTEmtuVxrWnE#L0#MMy7nnVEU5tSg1V&x<3_)n7U`iA;uYqNu z*1fIdd|}@o_PmWs&AKWKxbppGZ(x0$sgpAOP>;FhOp!`m*Ey|rxU#Wpih?3^IEU5I z85ic6!e-h;d17!`n%c=WL=f^1p)Y(Q43CF%wqu@}HpaFs4pS&VXZ0lV&6ba>(SJho BI8^`u literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b new file mode 100644 index 0000000..cce03e6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b @@ -0,0 +1,2 @@ +*? | " +%`Rw_Y} [QQ.=Rtw ~Pk.Q_k__k__sb_QRif_L_SrsX6i_____UmUzjWyiPsmrgXsPltOrO_____IVSLw_OSN_jnYu_umzY_Rj__v_.ddz,{hyPXrsvzzSWIkVwoY\x&xe#y%)\ICkMYJuZx_KCS_o55_nZ__7LH5_W-1-11252251225127[1162651257125xC2717e61862651257125- VZGohQpFpGtnpGPTniXq_JlK_F__t____GZ__F_Og__VMgb5955baBBBAfbB25929531253._--=x7___Tr438niX_R6q_JlK_mF__t2___4A957_AxmGZ_8_BF_Og_8_VM28cgw491186264514923957031250xbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031259101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253.0xDe15814980304091872B9EEaf48EDccB4b5Da0< \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43a26357597ae65521480220432ff645450d01f1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/43a26357597ae65521480220432ff645450d01f1 new file mode 100644 index 0000000000000000000000000000000000000000..2a895564edbda33ea529e17991573ebb6f983e7c GIT binary patch literal 1476 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 U`P?6Q-{F@6o;25A3STnuPyWOEjQ{`u literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/48bc76aeb21bc6070323247927d87e591e51eaa9-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/48bc76aeb21bc6070323247927d87e591e51eaa9-1 new file mode 100644 index 0000000000000000000000000000000000000000..699dc96c7e52cf74879af20e3dca24c7e1c6a484 GIT binary patch literal 984 zcmZ8fZFAB}7`0gIOKq>$`qo;xYVBCZCT@~VHqkmY0TK!gkU$~eI8Q?$5XwtJA<){f zf89m>;N1PN^PD+5&zy7ie801EbL-}0KEHjveLtd3`ciyzNxY&de7@_m^K$WWFU=85v=L2t1GG zDnb(3f7^Ad%}R|+i(X`0>v54IB@czdtbz;ashC0K7S1SkIN@{~wU^~oX(aUGEJ*`b zCmLuRoLx@g66Xk{92ta|h8+a}*(Shr2tWkXsRN$}O3D2YJWf%%jg+WQ4GH44<-@uN zldfC8ilqj$i9%zuc=pD#*Z)0ua${qMEx4D)u@!>cH**HvYiGz~sv9HB5kh!QqJTnP zL`YaaV7>zTa&s?P3GB&WW`&cmR2c_$l%EWW=IqgX2*c8N7~~s^AWwbM>3GEpuU~YW zBQtV>Xy8OHKQ6Ys6BqNLb#YR*%Vn!@vdJzbR@jyGwN>WN$9!B$FdHme82{GyM;=wj zpt+xN{Z^X}DOc5SyCth?2CF_MI^RkWvX1n4q4dS|29=seDc(Iwk!~TF)q4ml;ZP!LiDWPipq&|FXlk<>j=6|yz(A(OI}1>GPR7FTD!hMo l|8K{vZ(jVeeDpuh>_6+fn=7hAw@+6-`apYVE{gc#)labM8<_wA literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4959a4a9db83af17f9368cf490b8a0356d872147-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4959a4a9db83af17f9368cf490b8a0356d872147-1 new file mode 100644 index 0000000000000000000000000000000000000000..c139454f98318a17260f78385f20b7fe1480a40e GIT binary patch literal 298 zcmWlN`AfoJ0EV+eDMidENYW@NHJ$F>CrG#h&HGv&^M{YkZEBv&%?q=Cz4h|&@bISk z52>5e#q!>=#H-&-!0&0roz7tB7+&`yv4}ewa;(ZPueEERXv~JJ!tGd#SSRkz0f(Rp z$H^Ke>-yJEB71mrp_zd945%tl0c}HL81`=*=TwYSSxo?T02-&Uq({L-P_I(BQZYmv z5JXX+tn}N7JAAl&_T3gPHhZSSG$+mCG08BMPkq?UO}h-V*Z7z+9UVey2WP!;E)CNV zAKQO{!XYjp2u1N;bj$GSR?|>o-_F+H>F gLgFKHS^u6JB{MJ8+Okenp=nT%oa=2VzZf@16opyD5Eo*6Fvdg^C@?)XEhIK&6z2+HqvkD@~{6^e_Yer|*EkgY$+W>#R!6j!bDxhzU`ik%NzY zJ|U}Sdu14wC5pU&d+YgTQ+XXMC#{4*?ZjgS;|yFz(RF~k&E{3b?x?gQiuBYU;PlZP z*QHj$%_8m&`Saj94CvTCsq4v|iZ)Fa-R{`y>TKL^mL1Pbb4N*CD|G9*?$Tz=h{qMh zZpRs8h+kQPhBy|v3iB&T`7`5&AW1ENH7HG)c;Ao(G$18FwV7go(*U_DmdT(fCGh(% DrYB-T literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4b4859f278820e969c13c975669322e2c9df9823-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4b4859f278820e969c13c975669322e2c9df9823-5 new file mode 100644 index 0000000000000000000000000000000000000000..74187530ebf395fa3906abb54c6c85bed686b9c9 GIT binary patch literal 6 NcmZQ%U}0on0RR9a01E&B literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4d1adbc376464b88c52a00ed562cdacbffa4af1a-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/4d1adbc376464b88c52a00ed562cdacbffa4af1a-1 new file mode 100644 index 0000000000000000000000000000000000000000..028ba8762d949f7b3a47c6e7cb79a2949125b98e GIT binary patch literal 166 zcmY++y9&ZE7=~fJ0SE7+@+E)rCtZZ3$)J-Ucv?!Ev@9xa=l%gHjneZuA8d9R85S*^=(i&u~JeOcqT_PKxxg84Eh#ylcE$5mL)4KR4ECi tHXtE2p1JjvY@17)5a-DoO~!L`gI;K9XW*rmNA14ut}>>_vo_&n~p=`%;X?zb^6ho|ByW zXlYv2nEn1FpOfatQ6fJ0d~a+{EX z%!@1=xHjEyuE=H`SM<7$t-3NM|B!@xLqtRi$t=H9Gk(pRjyD{wi2^MJ>w+x6hH!OU zv;kO%Lwf%fu6uR5!&CbP<7(r?X2 z`l{VDERRp~jydd?sR$|&LH~kzK`iABpmW%H84d!0ugiF!S}!d`fCw-IZrOu809S`? ze}F;T#XwpElq#kVLOy-NoF0yID@6&$S{rgu_5qp(_P1E(F&|{GMHNaUL>0yB+K#k8 K%*g~{KKus-%wnbh literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/51c91bfe65eaa40fe4144306d6332ad84e4bb8ed-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/51c91bfe65eaa40fe4144306d6332ad84e4bb8ed-1 new file mode 100644 index 0000000..12301f1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/51c91bfe65eaa40fe4144306d6332ad84e4bb8ed-1 @@ -0,0 +1 @@ +GPTrniXRqJlK_mFt____AmGZ__BF_Og__VM_gw.4995325xC2aBABd731BEd3A7Aecb8dc866414295731253.0xDe9D94B9EEaf48EDccB4b5Da0-0x0e-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/53bcc0e78275d3efe9e012e6d30412066bf354f9-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/53bcc0e78275d3efe9e012e6d30412066bf354f9-2 new file mode 100644 index 0000000..e59672d --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/53bcc0e78275d3efe9e012e6d30412066bf354f9-2 @@ -0,0 +1 @@ +4995325233449559994-09-519341245142309503125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/545828581071b0d01c3fd9d15c7850c3f83ea15f-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/545828581071b0d01c3fd9d15c7850c3f83ea15f-2 new file mode 100644 index 0000000000000000000000000000000000000000..b8bf81e791b5de8fdb2be92a0d608098cdbe9661 GIT binary patch literal 25 gcmZQz6xh4}y_uPzg}JeTxw)~Wk*T?bp^@oo09*V9-v9sr literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/56860900c11ef30e85ce99b14e0e687745b269ae-9 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/56860900c11ef30e85ce99b14e0e687745b269ae-9 new file mode 100644 index 0000000000000000000000000000000000000000..794b9115f31f23c873c083fb25b0d69d2ab180e9 GIT binary patch literal 63 gcmZQ%U<5-JMixd0i;)2+0OW#1pppmykRUPy018b2W&i*H literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/581ed2fb7f25a6a5a8de40beae3dfd1666c511d0-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/581ed2fb7f25a6a5a8de40beae3dfd1666c511d0-2 new file mode 100644 index 0000000..a67655c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/581ed2fb7f25a6a5a8de40beae3dfd1666c511d0-2 @@ -0,0 +1 @@ +92309570312 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5b5d4262260375deb5146e3fa43f689923e856a7 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5b5d4262260375deb5146e3fa43f689923e856a7 new file mode 100644 index 0000000000000000000000000000000000000000..3340915b60239ddf0160f471cc9ccad228df1068 GIT binary patch literal 5895 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5c4b6679ee378f2533b099450ed21e40d54f6cd0-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5c4b6679ee378f2533b099450ed21e40d54f6cd0-3 new file mode 100644 index 0000000..e2127e6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5c4b6679ee378f2533b099450ed21e40d54f6cd0-3 @@ -0,0 +1 @@ +"465663981283077397778125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e13404b6713db5f2d4972747da143057beaaf64-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e13404b6713db5f2d4972747da143057beaaf64-2 new file mode 100644 index 0000000..2189bb4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e13404b6713db5f2d4972747da143057beaaf64-2 @@ -0,0 +1 @@ +012@456789@4567x \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e6c62abd0fe49668d26e9bfced0ef0dc699f6a5-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/5e6c62abd0fe49668d26e9bfced0ef0dc699f6a5-3 new file mode 100644 index 0000000000000000000000000000000000000000..90d6f0afc9e3672922a9eb27ba0699ba5691da89 GIT binary patch literal 32 ocmaFAe=oP0nFRxrxuKbXk>&2G8+XpAm%3vGyw5XLxmN#YQX+otZtPE+?1*G4@@N0+0F9S=x?aFd9n5JB3U%DR9+AS8n= zh)I6-SKpz(`WBr&N*|$5;7LWM-_Gng-|WuL?zh|j`IG)Xzg4~}rYNbeZ+`gn)n|9x zU;g;;>h$|crE&vr?!Wrlxc}@sBgNd%js6AOe-ZosH1@UBsk)}?qBw|SZ4hhfAW3lI z7QbCuuBw_TMkBSUMFVP^1~l+W4h>$vji`X4@^`w&Jvs=)yC>bS+HjpQJ6p1v=THr$ zXiN4ERX9?n(fEuCtyxJ>oZvhb+({_fF;yrOn!q;vv7tB1&6c_7*7R!lfW}j|RqHXk zw{~)%3+Bo}BW%rrpfh_pY+XKhv)R8`REHh$Bg?uB9(~bRUUV8q&UnULc1=T^6usf4 zH|v%_oRDHde6jqjPs*jvMTgixbX)9pJM2GiO)4#8Y}SHNrCV+{dskL|U)Qai2`((3v zx_9_-Hv8CffMLl+RoOy z+{wCkkfAn~_1(3f?&akc6%Fz>b9m>?rZrzI^y)A?OWi{p*^SkqrtjqmsYOA@^@n7}!Es1JBJkmA^k^cM1+U&n>&P84 hF#4tXh@!HY%=`B&_@GUhXNlGTi|6F`KML!A{s$%*A^iXV literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/60df0cda93981b671836008ff12625cd51171e9d b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/60df0cda93981b671836008ff12625cd51171e9d new file mode 100644 index 0000000000000000000000000000000000000000..e8054414abfbf771de0d86c5f6e0a88b622b9284 GIT binary patch literal 1776 zcmZWq3v=5<5O&hKxR01nrX>UtC>f^pG*We^$DKkU(aX#Ki zG|R6QO}kp9hFPUZ^suVgnpK;Hz8{NOc7La8`PQO8Gi$ScrD(2Vg_<9Rx*qDGqUoV+ zFRH#~ds?7)VVIirt$qL^XP)P&`)XCBK9y?K!WzZ^1HfyTT5VpZKb{}x`iGnN6O8eP zrDa&iq_oJfak1P3MVN`5%ye2fLi{-MKyYP<+g(JG})v48P3r{yT|9Z`CSX05< zZuyf*W=x;Tw2%%)nO3^kZFH|Z+jI8y{lxXX-)`5@W5);67<)44o1TC2~o~a7fN6&U9Ro zGb%4i?$KVH5iu_1cSYq{+_DPhW2kvfc1|<|WW) zUlN?=tRgN*^DbtsnI(Bb%o+`S_~!Y2?(ii3J>`!mN@J<$ilR4`w~3Ztw1i86)T31D z!2d6Bvfy4?z z;M(~>2tY;xQpXl1E3`=c&GW~PBlX_LZ|V;v>ETb$AcSk%XZiB$NR_C80wf752Nz-q zN)QX*LWpHZuM$~sp}+%#Bwj)&VD7U)5UA?vJfe(cB+4Qd1SGo*j$lSS!U$nLOL@T% zf$}8EsTF;SCG5CAi!}05y({vSjOK$DAUu! zh-Dd4B6$EsPKBz9c+9ChQYe9#vP~~B>J-rp@5rK#e1jrSS;qr+C=Pi(4~Z8s&y)uu zfh1p7Me>Z{MEHK~=7g?GD~n$)HCymBhUpeSfn^l0EeT9(G;b6G<|S=hZ<}^*ul%`l z|KGT@JG{FJa3aV;m$tCT3@Opg%PgTiBCeYRmXJo9B(0q60!RxQ0tnYkLkS#DV@@Y+ zq#a3e9CliOOPICuFi7_Un7O3PXLsPN*lE{o0Zz(`dh|z7w(2ZRZFOgT!hbRDU(H4) ina@`oBuC*nS+x9-MCM*@_uqSG6s|}~lVX=pR{jAGI|;S` literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/61077e99c801f3eb732ba4fae2296091eaea9c01-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/61077e99c801f3eb732ba4fae2296091eaea9c01-2 new file mode 100644 index 0000000000000000000000000000000000000000..1f19609c6737889f11cd76d35f44284cc8526016 GIT binary patch literal 109 zcmZRm=iw*|4)@HCRCZ2sNpg0vaB)nsah1#nEC|VrDD?97_stIU_9*uZ4Xw%vuguIX zh)Q*jijQ}T_fLL2AOGF^9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/612edfc64ec2f157158ac6b0b7bdceeb1338d3b8-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/612edfc64ec2f157158ac6b0b7bdceeb1338d3b8-6 new file mode 100644 index 0000000000000000000000000000000000000000..2dcac5c0c6a542ab1f2de355de90c7d6591ff314 GIT binary patch literal 8 PcmWgSWnf`rU}OLQ0T}=) literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/617132f8209014d1839691bc6c7d77e70ed60095-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/617132f8209014d1839691bc6c7d77e70ed60095-7 new file mode 100644 index 0000000000000000000000000000000000000000..8c3ffce1e3f23d1b3325d079338ed7dfeb95aec2 GIT binary patch literal 16 PcmZQ%U<5-JMhFA|0HgpJ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6182f2935dfb8967ce0d259c3fbc143167528f3b-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6182f2935dfb8967ce0d259c3fbc143167528f3b-1 new file mode 100644 index 0000000..3c11c80 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6182f2935dfb8967ce0d259c3fbc143167528f3b-1 @@ -0,0 +1 @@ +e11188721616029739CFeBEEbaE7fb-053440.-136868 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64bd2417583750313dd74d25c8b2f3eed25909a8 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64bd2417583750313dd74d25c8b2f3eed25909a8 new file mode 100644 index 0000000000000000000000000000000000000000..7ff626cf771e983fd725f5da2e7995381aca2b9f GIT binary patch literal 670 zcmZva*=rL~6vk_9MVlImOQA>wk)qO0yvy8KAVue9CTaFINz*hw9B0oq*~~J5VE=XR z^hrU^%g6bC=kVRbB@z)OQ7Tc!Xo?`lF3$G1+0@s}F=D9>o!k{`1QA40c(MJy{gSP{ zd3umNJ^UR`=i^Re7De?i%zUCWJ-KT&389DzSWM_b>OwITbFOl#8iA(BTvLc5%a0~g z5ygZ(AVrY{MS{IoJFTCqkNYq8Qs1^OE|10m|CL|IyM`>I?UM#ZXqTOGNB zet$W@mDn?U*YS1BvU8@FsX5IY8>Y`oR}HThTb85iDvdoSXQ`B1u4hs;5WLAfSCg5n zQ$0z+B*c6PAz5XTo+ye$TTbg3;m5!X{}UOBjXXzeZgR`=RH`BT_wwYOp8Ma)<6&=z zXOwMJdyV@#VjHp~W-e?5lW0}MvCN^ND$s8N@LIgQnZXQ-x&kXIH%Z9>K%hYjveFMY zefY3@^7*}K1gGgcv@61N!MYrCr+AI?swY!ChF!R$w;uo%43DKC9M& zDs=Ppuw4z;0b@2d0*5okGAHS?=etpUVHmL>AP@Brpj{>5nlQrRWjmJDNzY VC;#Bt2vqeRU;{=+BLF~_e*oUUx>x`J literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64dae3270e5806311fac4518cef7b473e2d3cd91-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64dae3270e5806311fac4518cef7b473e2d3cd91-4 new file mode 100644 index 0000000..83f6396 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/64dae3270e5806311fac4518cef7b473e2d3cd91-4 @@ -0,0 +1 @@ +"69128307397778125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/67519fd21225a9a0f3c5a86a76de43fd7234e1d4-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/67519fd21225a9a0f3c5a86a76de43fd7234e1d4-1 new file mode 100644 index 0000000..6ad7e9e --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/67519fd21225a9a0f3c5a86a76de43fd7234e1d4-1 @@ -0,0 +1 @@ +bDabBef136316160973937988281250xCc8Ed-0534420.-89113686837721616 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6b8432daf9022411b253dd7c8f5611c22cdc3895-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6b8432daf9022411b253dd7c8f5611c22cdc3895-2 new file mode 100644 index 0000000..7e367c9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6b8432daf9022411b253dd7c8f5611c22cdc3895-2 @@ -0,0 +1 @@ +11686837721616029739 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6d44323de19d56374597e2ac06e3beee133a42df b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6d44323de19d56374597e2ac06e3beee133a42df new file mode 100644 index 0000000..248aab2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/6d44323de19d56374597e2ac06e3beee133a42df @@ -0,0 +1,2 @@ +)+~\ zE!#TtSpei2D*kOySbJq4O!*e8xy- z9BF?DnhS|->XzjxR7F^~T+gJ+e2pr5E>>kCXv{Q1|0S64L_27`eQiG4PgjrO@;|&1(I<95U5auBMCcj5I>B@&XZ=tHJK~RY~@<2 z_nWyv5Dc==t3rMVna(``j6_1WE=nL>gtqPb^19%%quwAZeo-BE?nm{f@`K$-#*_P} z(n_>@GYY%6^_!;vp!`6BDbYwMuGCXHRk5B*HGIcag(uS}Cd(aAlp4ScQdN}*8#0E< EFFnt9@Bjb+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7f255b276b164c4309adbab19b872422d979c5e5 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7f255b276b164c4309adbab19b872422d979c5e5 new file mode 100644 index 0000000000000000000000000000000000000000..9e9eadabf04743a93c2cfc4a0f9428dcde3b6e94 GIT binary patch literal 1219 zcmZ9L2~XTc7=}3lp&?ySnzl4*q7o`KB-qT1XM9wfCgW@Gi)GmZq^VC>_JF;;gp^;t zQpZcANVO~<(tPtCew_Z{<;BbU?|#4kr}My6R<5O=Ui5xz_x|quc)gnG93LFL*~wh~ zTF8_p=bdtfdE@L>rB>gkv~49KU*09IujUsQ05S+880rubNY;Gn z`zEEPZ*_yfbQ~!N0?G6fbT;!-^@dX`^+?|tGy*~z>WfzD=Bjdgn=0RyhvU-aS>bXf zImyI_q10w4gWi~GgwYmby3I6UXnNPmc4jwDXnGh&p%9kBp)(r2+Fg8F9Q^sy&V9zVOOMH$C+CB$N~Jx> zty6lMZ(COKmxpJ^$$YW-%m9!oGWCf705GURJ=5b-fB@e$9BNs<0(8scmJ}L#uBqy= zEduxwi3kEPjnH<9=ZXR#L{bzYD*}L6hKL|UAOc7x5F;gV4gut$WXxYRBmphnfv*Ct zZs?|NS&|wHnNk?UGP2HPWFi3~kxk+Gmg|P%rwu+&9*2R%M1D`*w{PFQ%uyU~RWspO`9YWY1!wHnrXjt-V z4o3A(?c{Z(So^+EuTD`lGE~P20-0x+k7iB7!J+YFo;NYC2jlpI9!9R?YKE>;tcTo~ zXNH<*S~xT<>S(4LM5g!d^QNJiz8l4RU47li_>hCSSBK*M+S}dL`&REvY39ZEVsX54 z_LZ#hWuN19I_$R_CxdJ^XODZSmK~F(>pCG~WQ$Sa^%jVX=A5EQJ$>3p!))Ocq7IxM zt!&({^A;A#e|ZbvN{BmH96W4%dCbq_rzUW3SgJY8?A5huoIbH+`-F?K$Ag2+*hXTW zR}VjL7FZ8W`mJWRk1}0gH_O>p1^ktRai0A(;cdPcdf1ck?&?~rH-e=&*Xp%U5COL= zEG^r*Z+L##Rg~tup`zG*n!qeux-To-|MA|F?W5zLmzNjY;^>wkxmyEMJc2@Xsd>;4kM!3K3U=rTNIcR-n=6uaTQG!!|mM`Eg{6qq&( U`z(LTB>vY+zQ!iktZcIX0DH1l?EnA( literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7fca1fadd76fce238c82e9542eb05acd5bd38653-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7fca1fadd76fce238c82e9542eb05acd5bd38653-1 new file mode 100644 index 0000000..1e3d89c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/7fca1fadd76fce238c82e9542eb05acd5bd38653-1 @@ -0,0 +1 @@ +0123456789abcdefx \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8036c610dcec87d7bc42ba4ddddd660372392268-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8036c610dcec87d7bc42ba4ddddd660372392268-1 new file mode 100644 index 0000000000000000000000000000000000000000..591abacb3fadf58bebbf4f4c7ea63828eaa56354 GIT binary patch literal 111 zcmb=(s0@gYh<8dYDmE*ts)~xYjQ5In2@W^&%nmEhk4%eqPLksBow+ccfobpl_p*u3 z1%~m4>8>vEf$@gsrUs_w#s+3a2I8ic#v$g$si8gwrp6a1-nC@wS#ih2kww&S7ZL678)PvPal=A0|MuweUEVvq zFZ+%XcUgjAV&rqO2VKL<<+8GtMy-j`n0&`Ceh^#T4rH|IsD;`e`!_);M3ZYjisGAQyLE+Tl@&UeCY=X0Dpu2jrkLB`Mh`jXMbh+QD4t8_C zP$*0R$b%Y{1C+<>=a^@VJ=3IVjKKH%UTwx}Jc8i31mfw^ec&-6u$C^6I!%+&lUHPe zE6lLv)4Xt`te)CoIh)Jt77H@1Age=nz}DFD6-4E_KB literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/88b9cf63d84dab51dd67f44df0e64977da9dd7f2-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/88b9cf63d84dab51dd67f44df0e64977da9dd7f2-3 new file mode 100644 index 0000000000000000000000000000000000000000..4c2acc0ba32a8e45e4496711b29cf06c4bbdda50 GIT binary patch literal 23 ecmXpoG%`0eGq1VJP*GDDn>vtPExf4&~*`&&aCu$t?GcFZPTtjt2sD@7$>LbQc#_ zS7QTL7h`jmlw=bVOJf5|a|2^t1FmW|1E5e+MQW;AhApipLHuV4i literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/89f86a63a2de2d2877451bceaa2bd4e38abc8e64-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/89f86a63a2de2d2877451bceaa2bd4e38abc8e64-1 new file mode 100644 index 0000000000000000000000000000000000000000..ced275959bdc64aa352aba8b42609b0df3ac14d2 GIT binary patch literal 1648 zcmcIkYmd`L6fGbDZBYbBl?p0V1s^K4br{dXj-{p46FVWV&HKqp7dy7|es2;dLgJUN z)N5zi1=O#VY$qDuIdjgr=lb1~=NHd^{QhHcGP(C*@@ev}*?drJUR3ha*`PG|r8t`X zJ$YMgjPB$nuV4N3&&$UjbEQnCTpBzp<;vS`?fvRuwb?Evs-smQVVaHN$hObE`}Fhc zv*LO8<#1ZKe7qXg6WeiNSSoG{hiUWTqTLwf>cwsSe7xOu$9K!C=B&9mA69GA>S4S& zY&+-m#ET!o@MWxmDUH6K`6_#-TVL?bowX_qfSz0N^5-NI+X?5sWgt@PW5TDufayC?h2Fspngc!+hUomY1MJ5Jm-|9wVN`OdWAGsztRz zkKXvzWyBIm#vBLxM?tHXjT9`imCL~#pSLOiE|D(GvORp32LP?oU>_hMhcVL(Bozi_ z29gsj85)K(oInakNxUJUjyoD_hJHXzTLD@Evkc-Iu&5xSpoC06Mw*R&*$0=3@kj=elaso}J-7O%uZxo}&ciVC`%+0_cmUS66qhUj6=)N>rdijk-pd ziv2_(Y3f*}ZF?+5RQt0I*GfrGOE>c3Ir?R8fd3Fug<* z2pG9dHBIB_72!JmP?g|{itbW^VaMihopRj7H55l9srX)~oa%}91}Z(ZP`&NpwP7-n z`=TsC3#^6a|{cJO7Iqmc;D&hGlSR*tQe!lx_9JnAxJ^CAKKgu~a-WWZZ{H?A zA)&*{eW+{o_70|!bYQ${!)gkA$KXix1I@xhMHf5zP=f|!;Q$O$eZ2(6KA1zX0St}3 PWS#-rF;py2{HOl{i%r?% literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8c6d7def5f4465fc685347875a8e64e108b393df b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8c6d7def5f4465fc685347875a8e64e108b393df new file mode 100644 index 0000000..2131a20 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8c6d7def5f4465fc685347875a8e64e108b393df @@ -0,0 +1,2 @@ +)~\ <_______?;bE1bEC_AcyvP__FPI1bE1d_)+u::]~? +__j_5bu__yU__Dv19WNu_13g_Y1_RYWQvX______1z_L_G_k1Mm[_&_6d48_7V9_hSINhG8r__yj1_8_SWh_pGx_Nk_S1__u08_iZVaayDaTxoo%uj DcH11Q._'riRZU/ h_UO__63v2_G052"B_w34C_K1K.-Afc64ZmsVOt-'tqnf0x8f4E.-07__g.-03255663.-6&OyGOaL_h_Tt2Y1k717n1_7o6vN_KQ6MFXEO_2ANI4__z_l_a_PLn5Hm61_birB_/ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d43559e0f27f4a754db78baa697b37013f8a01d-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d43559e0f27f4a754db78baa697b37013f8a01d-1 new file mode 100644 index 0000000..f9a4ce2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d43559e0f27f4a754db78baa697b37013f8a01d-1 @@ -0,0 +1 @@ +-0xbafD8aae3Df5b9Bef111368683772161602973937988281250xCc3EBf357FEdaCfCF4CdeBEEbaE47fb5Bc691.-0xd-0Df5b9Bef11136868377216160297393797288281250xCc3EBf357FEdaCfCF4CdeBEEbaE47fb5Bcٻ691.-0xd-0534420.-8911368683772161602973534420.-89113686<37721 [616029739379882812 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d69ef1f7f28824fd8267ae8b36833e3e0b94765 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d69ef1f7f28824fd8267ae8b36833e3e0b94765 new file mode 100644 index 0000000..582dcab --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/8d69ef1f7f28824fd8267ae8b36833e3e0b94765 @@ -0,0 +1 @@ +-0757e0664060273074361272e0x2cF8a8E.-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-0xcA3.07047556026031-0x0e-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031257318e00017542035 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9239364aad81b3afb16be9487b5721a6fce7d375-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9239364aad81b3afb16be9487b5721a6fce7d375-2 new file mode 100644 index 0000000..edd3edd --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9239364aad81b3afb16be9487b5721a6fce7d375-2 @@ -0,0 +1 @@ +18695703125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9508e90548b0440a4a61e5743b76c1e309b23b7f-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9508e90548b0440a4a61e5743b76c1e309b23b7f-3 new file mode 100644 index 0000000000000000000000000000000000000000..12db4781e63a8c821478a5af5c840908f228181d GIT binary patch literal 3 KcmZQ%U;qFB1^@y8 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9567d94166370de252e759169b215fa8c2288746-11 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9567d94166370de252e759169b215fa8c2288746-11 new file mode 100644 index 0000000000000000000000000000000000000000..8f6fc5d28279a1d0b89f8df8737b15d96c60aa8b GIT binary patch literal 64 zcmZQ%1OoSxfTHBo;$q*_-29?S&%CsJpdf>xnSr?_BLjl~BLk2G5-dOnq`)+Y4T1oZ ChzNiH literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/962ecf57ef5bbb4107aaff02072f03d3316077c9-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/962ecf57ef5bbb4107aaff02072f03d3316077c9-1 new file mode 100644 index 0000000000000000000000000000000000000000..a143e7029bbb7fe22425d697eef2a83110e218fb GIT binary patch literal 817 zcmbu7OK+P%6ovbc+Ab>~RF$$TFi3;$Ip4j9`Fa0q|L{Y2w10B87&_}>d41=7+nBc@ zDmOux>4#LSvjL^Hx-1BPB78H-RJgt$XWSRAVj`~9fQ^vUG8+^7K?%!b=PMjtnplLx z3LqRyGkQvJH|g#H6T}PvZ5weLT6$7QOoow35QjE^h?+WITqO-3CdO9nYZbtAWBgYJZ~g|LkL+N5 zepAern@!ZH&TVHk?aJ7bxlSb$J(JQh^RVt)ry-IcPGRX}kU5DT&=h;nPFWIzteF+@ XY{n%1{AK%UyWLj*R8;wxbnoSFO#J83 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/96629c94c3faec6af9790f99bd72567d4534f9db b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/96629c94c3faec6af9790f99bd72567d4534f9db new file mode 100644 index 0000000000000000000000000000000000000000..2d4cb2d0d15834e8a2011862021f563f0a3fcf97 GIT binary patch literal 980 zcmYL{`A^$O7>0q;lZB-Ry;!B)QVM9XnemK0c1w%mB+ltLPSPY!7kxO+ePKglLZI!x z-hoQH(nvG!Z}0QWd$sjw>&N!mgT2Rpzu5S$>#C|+5A~bdR88I5cIW9k^~od|9Pcu~Kpy~8jfnrk(R1Pb&kcec zwE1oa5kh2!u#7~?WGQb2)qbhFvg>)DmqbDA`US(Pn68))_~5UN(` z(xPx6($kE=+eX_B`9z59pH>ml2-i-it|*kl6D-r2)GqHw_E+{JC*g88ZfFw0lXgs8 z5=GY@W{L?xI6CBlt|PnIP`S1An-0f0U$T=Kme%*z;q122WdTU24t?;jrgiHv*_b932ydOhjg(NS|7WGK@bcZ8 z_2&y8#8Eag^ygSpxfSSbAcavxF=I@^3J*L=GD74~_*RI60!IT;rN) zdMtUpDuZxF!&$Tr7pls)0W(RXkg_rV2mp1S8vtZFR+A?s=O<`h+>Mlb#mVTx_9uRU zKZERKWSJMwcFcU;K53gB&+>*=+6-#FU{niS$!dBom3;easaPu6`LD0U#ibv6YpW|l zq@O*@I%9(7O$RrdrmT(|8k@3FE3}xy$f=Fbn!G?-<(q|o^e>ZYR8|a-6_%_(o90G! zNim{R^YR?LkBiTQr(*uhohNg)uMW*jvIoTk6VR+3bKA|9KtwcC*N_nk-{9)!(^tC@ r_~+mc-!Ghvd)fN!wAn497Acxkr-TR?$+!vbhsh z$8Zf-(Zv=fz$QRQ88=}NuK=c?5KSXm>bb6CNRdupn5ID_t>@fPY8jzJWHIm^p7C+Y zsQH(PohTZ^kG?(p$K|J<7e%@*wu@Vlx@dr2oJ5LL#?bXpDNb z(K=?#6T-4$Uogg0EsaP)RapMz!M!+T0){aF*nrjNSY8pY;2cT>I{gv@R0gPZ5Xa-D IVWY2q0EVT(9smFU literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9b3ec560e1ed89789a09e834a18fb9f1d042f5dd-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9b3ec560e1ed89789a09e834a18fb9f1d042f5dd-2 new file mode 100644 index 0000000..e158e78 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9b3ec560e1ed89789a09e834a18fb9f1d042f5dd-2 @@ -0,0 +1 @@ +3095703125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9c61b17678d14d0b9ae09be017c6bbd6a3c3cabe-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9c61b17678d14d0b9ae09be017c6bbd6a3c3cabe-1 new file mode 100644 index 0000000..4e0f55f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9c61b17678d14d0b9ae09be017c6bbd6a3c3cabe-1 @@ -0,0 +1 @@ +412221647115710273365424.-0xaC4BFE3cCb3c7BE9 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9e3fc7fad4bf135219a974a8dac87e366f5b8e8c-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9e3fc7fad4bf135219a974a8dac87e366f5b8e8c-2 new file mode 100644 index 0000000..ce50acc --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/9e3fc7fad4bf135219a974a8dac87e366f5b8e8c-2 @@ -0,0 +1 @@ +111%613475767778796029739CFeBEEbaE7fb-053440.- \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a0bd71e19da9f0265508cdd2a50a458e5cd6bb19 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a0bd71e19da9f0265508cdd2a50a458e5cd6bb19 new file mode 100644 index 0000000000000000000000000000000000000000..cbd92cf77ae888c4ba4658f596469522e4519cbb GIT binary patch literal 1232 zcmbtT{ZA@K6cv3KW0e@wyjogq8`HjLEX#cE%qF(F3oJYk`H=54nJnzCf`EdHtSI`I zlXMnqn*PwFNpJRt**o{lxpU5)lh0?<{a;qoGN#|g&wiipU2gAhKJ9*e@Nr{%|NLlk z_x}8col)T+@$m7(SHGS;Z=AfWovwr@nZ4$h`%lqPwlL)~CXIcbusHV<{QRaj%T5Nq zW$+{a^lANdH#E3!7S2OE!;zP6nKi>Wc(TlXv%wpgY=z%E#P{Oz==Dz1bF6~_n@6wg=u-lN0^>d~-kXJ2S z)$&(U*D{QN+E~_>?qqdwSzi2?dioBalqyt#lp^v?+_!bvhohy;6txmb+laO5zb#D( zKd)`Q&KHZtNp$hDChu*lNR^*l*iNusIXzra!gE4$$eE!G@<`W16BVkNJv1)Zohm`~ zQnh?}S-PlhM@o0)oT4a^$2Yxa(Z`45RSl|;Fee6lwe8qUvrV(@tRn=2kQ4+G4FQb- zh``^nO92@NFc48^`cg-gEFB0S^bJD;5UtIC&))2~?K#pA+7}pSQBk-PF%TF43<7tU z>$E#e(-;mcN(LS=3<8EEmV2Fck_QZ&P@-X=$-^-{0+cDT^UbGqfEYszQh+hRh#<@; zMhqi}DNq?v36p^#Rbm(d%z)ei8UTNUR^#GPiM{zw$-DFa#m#@%348~eN{mJhHevun zhA~Be5Uf&_04n7KMD~XiDKxZEr=wd*ZY6ZHgWK3lrIHp*!dRcNrg#*3gCijXnuxl{ zU{PsgsDN1^@)bGZH$|3!5Ao%IM4n^8)B1j~u@$Yp%>T!PNIE$r;;$)@fA67)9;x-K zS1281JT%3(;2|@BwfMTVhibnvNKmG}?LtxVY literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a3c5cb453e89aef7359f952459685c26cea30d63-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a3c5cb453e89aef7359f952459685c26cea30d63-1 new file mode 100644 index 0000000000000000000000000000000000000000..3b5ad6f37a7306f11e8e2fbe95dd4ff115821168 GIT binary patch literal 53 zcmXpse7}D$Hv^NIp_ze^uVE16vYJ4?cWr;ab1-R6?tS^Cy-AzB zv_A{frw75_`R1%Yndm|3Pv9PTdxd{w@0H&I;zz71}Dv()80nfue557EhWoXU?%|+jOjv%L^^@5J^gI% zjjfB)zL!#4n9|NvkL7r^HdxTuvf48$EXptyNGvaqMS)ZH9oKfGj7)VCM@Ft~+R5TN z)QRvv&@}xY(8(T?;doyo=ML){Md*&;tG|| zm6oSawHaeRaY*7A%pi=Yf!)@2w$Wy5?O8Q3_xtb`Fo0pTvCB7S5Q}LIcHwJ+Bj^nH;S{EQ zIcJ9$BoR9uSWhB215MA|FvcaVz@>aMEUvk}B35Lw#L8;9jY`d*ahKUQw%OOpHoWwqOw4G)!tGK|W;l&*SHE{#G?slkp=7TQEd zh%&~J!4X-EjMe5ErX?fc$K0{Qr1XB_;il}aTwJ`Z8*;zy2LI=r)ergWqx?nQW3@W4 eo=Qu_!lq%X7G(g+))`PRw_qSGI5nV}J^KrjpdF(C literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a5ef3d034850ec9510bb931f21a1547518a76f14 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a5ef3d034850ec9510bb931f21a1547518a76f14 new file mode 100644 index 0000000..4be5c9e --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a5ef3d034850ec9510bb931f21a1547518a76f14 @@ -0,0 +1 @@ +/ddDDd333DDDD33dDd3EdD3Dd23323DDEEED.=2320C2DEd7380EdD7AeD8Bd812370312001.0x01x2.01077e231171320353722057202000015.0413204 xEaae2e0.QTRKOMafB55.QxKHfUmUgWPfmgesPptx7ACR8aoILeONf6um5ERf-.-8785.-xd-,|e@.EZt15ms1V7nOPYOLtiLl.-<6"xaaee66.hQppGPtnpGPTrniXRqlKFtGZFOVMgaf555.fVZGohQpFpGPtgnpGPTrniXRqJlKFtmGZFOg__VMgwbBfbB955bBaBBBAAfbB592953253.3sqy5j_4_hFIS_j-_-x7___Tr4438niX_R6q_Jl\_mF__t2___4A957_EAxmGZ_8_BF_Og_8_VM28gw1641492953125xbC2aBABE73801BEAAfebdc86644973125-9101862645149230957031250xdbBC2aBABEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253.0xDe9D94B9EEaf48EDccB4b5Da0-0xebeA4298b51AD6-R8Z1-66E_a__Z_n_oIVS6Lw_e9uO_1S_Nf1d_jn56Yu_umEz5Y1_E39Rj_Jfd_v_-.-0058291178955.-0xd1b-9101_626519230957031250xdbBC2aBBEEd73801BEd37feb864Bdc1862645149230957031253Vz-0x7AC8Ddb%hyPXrs6vzzZJSWIkVwoY__aC_pCaEEDAfbD4dc64425+ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a70573a8edabc05a2431773757158ac90e63d43a-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a70573a8edabc05a2431773757158ac90e63d43a-1 new file mode 100644 index 0000000..0fd087f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a70573a8edabc05a2431773757158ac90e63d43a-1 @@ -0,0 +1 @@ +bbf.VZGohQpFpGPtgnpGPTrniX_Rq_JlK_F__t____mGZ__F_Og__VMgwbBBfbB9959955bBaBB3B3AAfb4B24549239531253.x994B9af4EccB4b5a-9101_24514923095031250xdbBC2aBDABEEd301BEcdD3A7AfecbD4Bdc12645149230957031253Vz-0x7___Tr4438niX_R6q_JlK_mF__t2___4A957_EAxmGZ_8_BF_O0g_8_VM28cgw49101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253.0xDe9D94B9EEaf48EDccB4b5Da0-9101_62645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253Vz-0x7AC8Ddb \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d099f456e0a9444c10bf1cdfe788da8f65f8d5-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d099f456e0a9444c10bf1cdfe788da8f65f8d5-6 new file mode 100644 index 0000000000000000000000000000000000000000..e075e6eb7c405311c19497e3bfcf8cbac9831023 GIT binary patch literal 11 ScmZQz2xMVoWMN@s2m}BFi2$+y literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d2bd34ee5b24064975a68298bfa566b63a133c-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d2bd34ee5b24064975a68298bfa566b63a133c-2 new file mode 100644 index 0000000..ffc901c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/a8d2bd34ee5b24064975a68298bfa566b63a133c-2 @@ -0,0 +1 @@ +bbf.VZGohQpFpGPtgnpGPTrniX_Rq_JlK_F__t____mGZ__F_Og__VMgwbBBfbB9959955bBaBB3B3AAfb4B24549239531253.x994B9af4EccB4b5a-9101_24514923095031250xdbBC2aBDABEEd301BEcdD3A7AfecbD4Bdc12645149230957031253Vz-0x7___Tr4438niX_R6q_Jl\_mF__t2___4A957_EAxmGZ_8_BF_O0g_8_VM28cgw49101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253.0xDe9D94B9EEaf48EDccB4b5Da0-9101_62645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253Vz-0x7AC8Ddb \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ac04c28afed2d337f787d007a992e8ec7f937b36 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ac04c28afed2d337f787d007a992e8ec7f937b36 new file mode 100644 index 0000000..e8a1dff --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ac04c28afed2d337f787d007a992e8ec7f937b36 @@ -0,0 +1 @@ +efZohQpggnpGPTrniXRqJlKmFt__mGZ__F_Og__VM_gw.xAAfeB643xbBCaBABE3BEcd3AAfecbD64Bdc866449239703230xDe9D94B9EEaf48EDccB4b5Da0-0xB66C9fad.-75946554523692857652911-i1V___hoNaqWTStRM9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031259101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-0xe \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ad336c19a004476640934db99f827f2917a09bf8 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ad336c19a004476640934db99f827f2917a09bf8 new file mode 100644 index 0000000000000000000000000000000000000000..a76a3e6d9da6828c0807ebbc4f8d6093dfd57900 GIT binary patch literal 17674 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 VrZQ7!QPCU*O1E1p=}yD>e*jL`S)u>{ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/aef8193ef7e7916cebd428e02ae7c9081b9e56a1-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/aef8193ef7e7916cebd428e02ae7c9081b9e56a1-6 new file mode 100644 index 0000000000000000000000000000000000000000..dc8b0c1cabeb1e4d6422315927e2989ea165d64e GIT binary patch literal 12 TcmZRGXNYHD6lREzXJh~X3XB1g literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/af640328532d29ae2f935b87564cb595f6cbb54e b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/af640328532d29ae2f935b87564cb595f6cbb54e new file mode 100644 index 0000000000000000000000000000000000000000..60da00c87efe9105a52223574ff21d0b1a1ea97c GIT binary patch literal 1035 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/zip/reader.go b/vendor/github.com/klauspost/compress/zip/reader.go index 27199dd..9a0e20d 100644 --- a/vendor/github.com/klauspost/compress/zip/reader.go +++ b/vendor/github.com/klauspost/compress/zip/reader.go @@ -10,10 +10,9 @@ import ( "errors" "fmt" "hash" + "hash/crc32" "io" "os" - - "github.com/klauspost/crc32" ) var ( diff --git a/vendor/github.com/klauspost/compress/zip/writer.go b/vendor/github.com/klauspost/compress/zip/writer.go index 5843958..5ce66e6 100644 --- a/vendor/github.com/klauspost/compress/zip/writer.go +++ b/vendor/github.com/klauspost/compress/zip/writer.go @@ -9,9 +9,8 @@ import ( "encoding/binary" "errors" "hash" + "hash/crc32" "io" - - "github.com/klauspost/crc32" ) // TODO(adg): support zip file comments diff --git a/vendor/github.com/klauspost/compress/zlib/reader.go b/vendor/github.com/klauspost/compress/zlib/reader.go index b78a2c1..d9091e8 100644 --- a/vendor/github.com/klauspost/compress/zlib/reader.go +++ b/vendor/github.com/klauspost/compress/zlib/reader.go @@ -128,7 +128,7 @@ func (z *reader) Close() error { } func (z *reader) Reset(r io.Reader, dict []byte) error { - *z = reader{decompressor: z.decompressor} + *z = reader{decompressor: z.decompressor, digest: z.digest} if fr, ok := r.(flate.Reader); ok { z.r = fr } else { @@ -173,6 +173,11 @@ func (z *reader) Reset(r io.Reader, dict []byte) error { } else { z.decompressor.(flate.Resetter).Reset(z.r, dict) } - z.digest = adler32.New() + + if z.digest != nil { + z.digest.Reset() + } else { + z.digest = adler32.New() + } return nil } diff --git a/vendor/github.com/klauspost/crc32/.gitignore b/vendor/github.com/klauspost/crc32/.gitignore deleted file mode 100644 index daf913b..0000000 --- a/vendor/github.com/klauspost/crc32/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/klauspost/crc32/.travis.yml b/vendor/github.com/klauspost/crc32/.travis.yml deleted file mode 100644 index de64ae4..0000000 --- a/vendor/github.com/klauspost/crc32/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - tip - -script: - - go test -v . - - go test -v -race . diff --git a/vendor/github.com/klauspost/crc32/README.md b/vendor/github.com/klauspost/crc32/README.md deleted file mode 100644 index 029625d..0000000 --- a/vendor/github.com/klauspost/crc32/README.md +++ /dev/null @@ -1,87 +0,0 @@ -# crc32 -CRC32 hash with x64 optimizations - -This package is a drop-in replacement for the standard library `hash/crc32` package, that features SSE 4.2 optimizations on x64 platforms, for a 10x speedup. - -[![Build Status](https://travis-ci.org/klauspost/crc32.svg?branch=master)](https://travis-ci.org/klauspost/crc32) - -# usage - -Install using `go get github.com/klauspost/crc32`. This library is based on Go 1.5 code and requires Go 1.3 or newer. - -Replace `import "hash/crc32"` with `import "github.com/klauspost/crc32"` and you are good to go. - -# changes -* Oct 20, 2016: Changes have been merged to upstream Go. Package updated to match. -* Dec 4, 2015: Uses the "slice-by-8" trick more extensively, which gives a 1.5 to 2.5x speedup if assembler is unavailable. - - -# performance - -For *Go 1.7* performance is equivalent to the standard library. So if you use this package for Go 1.7 you can switch back. - - -For IEEE tables (the most common), there is approximately a factor 10 speedup with "CLMUL" (Carryless multiplication) instruction: -``` -benchmark old ns/op new ns/op delta -BenchmarkCrc32KB 99955 10258 -89.74% - -benchmark old MB/s new MB/s speedup -BenchmarkCrc32KB 327.83 3194.20 9.74x -``` - -For other tables and "CLMUL" capable machines the performance is the same as the standard library. - -Here are some detailed benchmarks, comparing to go 1.5 standard library with and without assembler enabled. - -``` -Std: Standard Go 1.5 library -Crc: Indicates IEEE type CRC. -40B: Size of each slice encoded. -NoAsm: Assembler was disabled (ie. not an AMD64 or SSE 4.2+ capable machine). -Castagnoli: Castagnoli CRC type. - -BenchmarkStdCrc40B-4 10000000 158 ns/op 252.88 MB/s -BenchmarkCrc40BNoAsm-4 20000000 105 ns/op 377.38 MB/s (slice8) -BenchmarkCrc40B-4 20000000 105 ns/op 378.77 MB/s (slice8) - -BenchmarkStdCrc1KB-4 500000 3604 ns/op 284.10 MB/s -BenchmarkCrc1KBNoAsm-4 1000000 1463 ns/op 699.79 MB/s (slice8) -BenchmarkCrc1KB-4 3000000 396 ns/op 2583.69 MB/s (asm) - -BenchmarkStdCrc8KB-4 200000 11417 ns/op 717.48 MB/s (slice8) -BenchmarkCrc8KBNoAsm-4 200000 11317 ns/op 723.85 MB/s (slice8) -BenchmarkCrc8KB-4 500000 2919 ns/op 2805.73 MB/s (asm) - -BenchmarkStdCrc32KB-4 30000 45749 ns/op 716.24 MB/s (slice8) -BenchmarkCrc32KBNoAsm-4 30000 45109 ns/op 726.42 MB/s (slice8) -BenchmarkCrc32KB-4 100000 11497 ns/op 2850.09 MB/s (asm) - -BenchmarkStdNoAsmCastagnol40B-4 10000000 161 ns/op 246.94 MB/s -BenchmarkStdCastagnoli40B-4 50000000 28.4 ns/op 1410.69 MB/s (asm) -BenchmarkCastagnoli40BNoAsm-4 20000000 100 ns/op 398.01 MB/s (slice8) -BenchmarkCastagnoli40B-4 50000000 28.2 ns/op 1419.54 MB/s (asm) - -BenchmarkStdNoAsmCastagnoli1KB-4 500000 3622 ns/op 282.67 MB/s -BenchmarkStdCastagnoli1KB-4 10000000 144 ns/op 7099.78 MB/s (asm) -BenchmarkCastagnoli1KBNoAsm-4 1000000 1475 ns/op 694.14 MB/s (slice8) -BenchmarkCastagnoli1KB-4 10000000 146 ns/op 6993.35 MB/s (asm) - -BenchmarkStdNoAsmCastagnoli8KB-4 50000 28781 ns/op 284.63 MB/s -BenchmarkStdCastagnoli8KB-4 1000000 1029 ns/op 7957.89 MB/s (asm) -BenchmarkCastagnoli8KBNoAsm-4 200000 11410 ns/op 717.94 MB/s (slice8) -BenchmarkCastagnoli8KB-4 1000000 1000 ns/op 8188.71 MB/s (asm) - -BenchmarkStdNoAsmCastagnoli32KB-4 10000 115426 ns/op 283.89 MB/s -BenchmarkStdCastagnoli32KB-4 300000 4065 ns/op 8059.13 MB/s (asm) -BenchmarkCastagnoli32KBNoAsm-4 30000 45171 ns/op 725.41 MB/s (slice8) -BenchmarkCastagnoli32KB-4 500000 4077 ns/op 8035.89 MB/s (asm) -``` - -The IEEE assembler optimizations has been submitted and will be part of the Go 1.6 standard library. - -However, the improved use of slice-by-8 has not, but will probably be submitted for Go 1.7. - -# license - -Standard Go license. Changes are Copyright (c) 2015 Klaus Post under same conditions. diff --git a/vendor/github.com/klauspost/crc32/crc32.go b/vendor/github.com/klauspost/crc32/crc32.go deleted file mode 100644 index 8aa91b1..0000000 --- a/vendor/github.com/klauspost/crc32/crc32.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32, -// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for -// information. -// -// Polynomials are represented in LSB-first form also known as reversed representation. -// -// See http://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials -// for information. -package crc32 - -import ( - "hash" - "sync" -) - -// The size of a CRC-32 checksum in bytes. -const Size = 4 - -// Predefined polynomials. -const ( - // IEEE is by far and away the most common CRC-32 polynomial. - // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ... - IEEE = 0xedb88320 - - // Castagnoli's polynomial, used in iSCSI. - // Has better error detection characteristics than IEEE. - // http://dx.doi.org/10.1109/26.231911 - Castagnoli = 0x82f63b78 - - // Koopman's polynomial. - // Also has better error detection characteristics than IEEE. - // http://dx.doi.org/10.1109/DSN.2002.1028931 - Koopman = 0xeb31d82e -) - -// Table is a 256-word table representing the polynomial for efficient processing. -type Table [256]uint32 - -// This file makes use of functions implemented in architecture-specific files. -// The interface that they implement is as follows: -// -// // archAvailableIEEE reports whether an architecture-specific CRC32-IEEE -// // algorithm is available. -// archAvailableIEEE() bool -// -// // archInitIEEE initializes the architecture-specific CRC3-IEEE algorithm. -// // It can only be called if archAvailableIEEE() returns true. -// archInitIEEE() -// -// // archUpdateIEEE updates the given CRC32-IEEE. It can only be called if -// // archInitIEEE() was previously called. -// archUpdateIEEE(crc uint32, p []byte) uint32 -// -// // archAvailableCastagnoli reports whether an architecture-specific -// // CRC32-C algorithm is available. -// archAvailableCastagnoli() bool -// -// // archInitCastagnoli initializes the architecture-specific CRC32-C -// // algorithm. It can only be called if archAvailableCastagnoli() returns -// // true. -// archInitCastagnoli() -// -// // archUpdateCastagnoli updates the given CRC32-C. It can only be called -// // if archInitCastagnoli() was previously called. -// archUpdateCastagnoli(crc uint32, p []byte) uint32 - -// castagnoliTable points to a lazily initialized Table for the Castagnoli -// polynomial. MakeTable will always return this value when asked to make a -// Castagnoli table so we can compare against it to find when the caller is -// using this polynomial. -var castagnoliTable *Table -var castagnoliTable8 *slicing8Table -var castagnoliArchImpl bool -var updateCastagnoli func(crc uint32, p []byte) uint32 -var castagnoliOnce sync.Once - -func castagnoliInit() { - castagnoliTable = simpleMakeTable(Castagnoli) - castagnoliArchImpl = archAvailableCastagnoli() - - if castagnoliArchImpl { - archInitCastagnoli() - updateCastagnoli = archUpdateCastagnoli - } else { - // Initialize the slicing-by-8 table. - castagnoliTable8 = slicingMakeTable(Castagnoli) - updateCastagnoli = func(crc uint32, p []byte) uint32 { - return slicingUpdate(crc, castagnoliTable8, p) - } - } -} - -// IEEETable is the table for the IEEE polynomial. -var IEEETable = simpleMakeTable(IEEE) - -// ieeeTable8 is the slicing8Table for IEEE -var ieeeTable8 *slicing8Table -var ieeeArchImpl bool -var updateIEEE func(crc uint32, p []byte) uint32 -var ieeeOnce sync.Once - -func ieeeInit() { - ieeeArchImpl = archAvailableIEEE() - - if ieeeArchImpl { - archInitIEEE() - updateIEEE = archUpdateIEEE - } else { - // Initialize the slicing-by-8 table. - ieeeTable8 = slicingMakeTable(IEEE) - updateIEEE = func(crc uint32, p []byte) uint32 { - return slicingUpdate(crc, ieeeTable8, p) - } - } -} - -// MakeTable returns a Table constructed from the specified polynomial. -// The contents of this Table must not be modified. -func MakeTable(poly uint32) *Table { - switch poly { - case IEEE: - ieeeOnce.Do(ieeeInit) - return IEEETable - case Castagnoli: - castagnoliOnce.Do(castagnoliInit) - return castagnoliTable - } - return simpleMakeTable(poly) -} - -// digest represents the partial evaluation of a checksum. -type digest struct { - crc uint32 - tab *Table -} - -// New creates a new hash.Hash32 computing the CRC-32 checksum -// using the polynomial represented by the Table. -// Its Sum method will lay the value out in big-endian byte order. -func New(tab *Table) hash.Hash32 { - if tab == IEEETable { - ieeeOnce.Do(ieeeInit) - } - return &digest{0, tab} -} - -// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum -// using the IEEE polynomial. -// Its Sum method will lay the value out in big-endian byte order. -func NewIEEE() hash.Hash32 { return New(IEEETable) } - -func (d *digest) Size() int { return Size } - -func (d *digest) BlockSize() int { return 1 } - -func (d *digest) Reset() { d.crc = 0 } - -// Update returns the result of adding the bytes in p to the crc. -func Update(crc uint32, tab *Table, p []byte) uint32 { - switch tab { - case castagnoliTable: - return updateCastagnoli(crc, p) - case IEEETable: - // Unfortunately, because IEEETable is exported, IEEE may be used without a - // call to MakeTable. We have to make sure it gets initialized in that case. - ieeeOnce.Do(ieeeInit) - return updateIEEE(crc, p) - default: - return simpleUpdate(crc, tab, p) - } -} - -func (d *digest) Write(p []byte) (n int, err error) { - switch d.tab { - case castagnoliTable: - d.crc = updateCastagnoli(d.crc, p) - case IEEETable: - // We only create digest objects through New() which takes care of - // initialization in this case. - d.crc = updateIEEE(d.crc, p) - default: - d.crc = simpleUpdate(d.crc, d.tab, p) - } - return len(p), nil -} - -func (d *digest) Sum32() uint32 { return d.crc } - -func (d *digest) Sum(in []byte) []byte { - s := d.Sum32() - return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) -} - -// Checksum returns the CRC-32 checksum of data -// using the polynomial represented by the Table. -func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) } - -// ChecksumIEEE returns the CRC-32 checksum of data -// using the IEEE polynomial. -func ChecksumIEEE(data []byte) uint32 { - ieeeOnce.Do(ieeeInit) - return updateIEEE(0, data) -} diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64.go b/vendor/github.com/klauspost/crc32/crc32_amd64.go deleted file mode 100644 index af2a0b8..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_amd64.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2011 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. - -// +build !appengine,!gccgo - -// AMD64-specific hardware-assisted CRC32 algorithms. See crc32.go for a -// description of the interface that each architecture-specific file -// implements. - -package crc32 - -import "unsafe" - -// This file contains the code to call the SSE 4.2 version of the Castagnoli -// and IEEE CRC. - -// haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and use -// CPUID to test for SSE 4.1, 4.2 and CLMUL support. -func haveSSE41() bool -func haveSSE42() bool -func haveCLMUL() bool - -// castagnoliSSE42 is defined in crc32_amd64.s and uses the SSE4.2 CRC32 -// instruction. -//go:noescape -func castagnoliSSE42(crc uint32, p []byte) uint32 - -// castagnoliSSE42Triple is defined in crc32_amd64.s and uses the SSE4.2 CRC32 -// instruction. -//go:noescape -func castagnoliSSE42Triple( - crcA, crcB, crcC uint32, - a, b, c []byte, - rounds uint32, -) (retA uint32, retB uint32, retC uint32) - -// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ -// instruction as well as SSE 4.1. -//go:noescape -func ieeeCLMUL(crc uint32, p []byte) uint32 - -var sse42 = haveSSE42() -var useFastIEEE = haveCLMUL() && haveSSE41() - -const castagnoliK1 = 168 -const castagnoliK2 = 1344 - -type sse42Table [4]Table - -var castagnoliSSE42TableK1 *sse42Table -var castagnoliSSE42TableK2 *sse42Table - -func archAvailableCastagnoli() bool { - return sse42 -} - -func archInitCastagnoli() { - if !sse42 { - panic("arch-specific Castagnoli not available") - } - castagnoliSSE42TableK1 = new(sse42Table) - castagnoliSSE42TableK2 = new(sse42Table) - // See description in updateCastagnoli. - // t[0][i] = CRC(i000, O) - // t[1][i] = CRC(0i00, O) - // t[2][i] = CRC(00i0, O) - // t[3][i] = CRC(000i, O) - // where O is a sequence of K zeros. - var tmp [castagnoliK2]byte - for b := 0; b < 4; b++ { - for i := 0; i < 256; i++ { - val := uint32(i) << uint32(b*8) - castagnoliSSE42TableK1[b][i] = castagnoliSSE42(val, tmp[:castagnoliK1]) - castagnoliSSE42TableK2[b][i] = castagnoliSSE42(val, tmp[:]) - } - } -} - -// castagnoliShift computes the CRC32-C of K1 or K2 zeroes (depending on the -// table given) with the given initial crc value. This corresponds to -// CRC(crc, O) in the description in updateCastagnoli. -func castagnoliShift(table *sse42Table, crc uint32) uint32 { - return table[3][crc>>24] ^ - table[2][(crc>>16)&0xFF] ^ - table[1][(crc>>8)&0xFF] ^ - table[0][crc&0xFF] -} - -func archUpdateCastagnoli(crc uint32, p []byte) uint32 { - if !sse42 { - panic("not available") - } - - // This method is inspired from the algorithm in Intel's white paper: - // "Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction" - // The same strategy of splitting the buffer in three is used but the - // combining calculation is different; the complete derivation is explained - // below. - // - // -- The basic idea -- - // - // The CRC32 instruction (available in SSE4.2) can process 8 bytes at a - // time. In recent Intel architectures the instruction takes 3 cycles; - // however the processor can pipeline up to three instructions if they - // don't depend on each other. - // - // Roughly this means that we can process three buffers in about the same - // time we can process one buffer. - // - // The idea is then to split the buffer in three, CRC the three pieces - // separately and then combine the results. - // - // Combining the results requires precomputed tables, so we must choose a - // fixed buffer length to optimize. The longer the length, the faster; but - // only buffers longer than this length will use the optimization. We choose - // two cutoffs and compute tables for both: - // - one around 512: 168*3=504 - // - one around 4KB: 1344*3=4032 - // - // -- The nitty gritty -- - // - // Let CRC(I, X) be the non-inverted CRC32-C of the sequence X (with - // initial non-inverted CRC I). This function has the following properties: - // (a) CRC(I, AB) = CRC(CRC(I, A), B) - // (b) CRC(I, A xor B) = CRC(I, A) xor CRC(0, B) - // - // Say we want to compute CRC(I, ABC) where A, B, C are three sequences of - // K bytes each, where K is a fixed constant. Let O be the sequence of K zero - // bytes. - // - // CRC(I, ABC) = CRC(I, ABO xor C) - // = CRC(I, ABO) xor CRC(0, C) - // = CRC(CRC(I, AB), O) xor CRC(0, C) - // = CRC(CRC(I, AO xor B), O) xor CRC(0, C) - // = CRC(CRC(I, AO) xor CRC(0, B), O) xor CRC(0, C) - // = CRC(CRC(CRC(I, A), O) xor CRC(0, B), O) xor CRC(0, C) - // - // The castagnoliSSE42Triple function can compute CRC(I, A), CRC(0, B), - // and CRC(0, C) efficiently. We just need to find a way to quickly compute - // CRC(uvwx, O) given a 4-byte initial value uvwx. We can precompute these - // values; since we can't have a 32-bit table, we break it up into four - // 8-bit tables: - // - // CRC(uvwx, O) = CRC(u000, O) xor - // CRC(0v00, O) xor - // CRC(00w0, O) xor - // CRC(000x, O) - // - // We can compute tables corresponding to the four terms for all 8-bit - // values. - - crc = ^crc - - // If a buffer is long enough to use the optimization, process the first few - // bytes to align the buffer to an 8 byte boundary (if necessary). - if len(p) >= castagnoliK1*3 { - delta := int(uintptr(unsafe.Pointer(&p[0])) & 7) - if delta != 0 { - delta = 8 - delta - crc = castagnoliSSE42(crc, p[:delta]) - p = p[delta:] - } - } - - // Process 3*K2 at a time. - for len(p) >= castagnoliK2*3 { - // Compute CRC(I, A), CRC(0, B), and CRC(0, C). - crcA, crcB, crcC := castagnoliSSE42Triple( - crc, 0, 0, - p, p[castagnoliK2:], p[castagnoliK2*2:], - castagnoliK2/24) - - // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B) - crcAB := castagnoliShift(castagnoliSSE42TableK2, crcA) ^ crcB - // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C) - crc = castagnoliShift(castagnoliSSE42TableK2, crcAB) ^ crcC - p = p[castagnoliK2*3:] - } - - // Process 3*K1 at a time. - for len(p) >= castagnoliK1*3 { - // Compute CRC(I, A), CRC(0, B), and CRC(0, C). - crcA, crcB, crcC := castagnoliSSE42Triple( - crc, 0, 0, - p, p[castagnoliK1:], p[castagnoliK1*2:], - castagnoliK1/24) - - // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B) - crcAB := castagnoliShift(castagnoliSSE42TableK1, crcA) ^ crcB - // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C) - crc = castagnoliShift(castagnoliSSE42TableK1, crcAB) ^ crcC - p = p[castagnoliK1*3:] - } - - // Use the simple implementation for what's left. - crc = castagnoliSSE42(crc, p) - return ^crc -} - -func archAvailableIEEE() bool { - return useFastIEEE -} - -var archIeeeTable8 *slicing8Table - -func archInitIEEE() { - if !useFastIEEE { - panic("not available") - } - // We still use slicing-by-8 for small buffers. - archIeeeTable8 = slicingMakeTable(IEEE) -} - -func archUpdateIEEE(crc uint32, p []byte) uint32 { - if !useFastIEEE { - panic("not available") - } - - if len(p) >= 64 { - left := len(p) & 15 - do := len(p) - left - crc = ^ieeeCLMUL(^crc, p[:do]) - p = p[do:] - } - if len(p) == 0 { - return crc - } - return slicingUpdate(crc, archIeeeTable8, p) -} diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64.s b/vendor/github.com/klauspost/crc32/crc32_amd64.s deleted file mode 100644 index e8a7941..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_amd64.s +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2011 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. - -// +build gc - -#define NOSPLIT 4 -#define RODATA 8 - -// castagnoliSSE42 updates the (non-inverted) crc with the given buffer. -// -// func castagnoliSSE42(crc uint32, p []byte) uint32 -TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 - MOVL crc+0(FP), AX // CRC value - MOVQ p+8(FP), SI // data pointer - MOVQ p_len+16(FP), CX // len(p) - - // If there are fewer than 8 bytes to process, skip alignment. - CMPQ CX, $8 - JL less_than_8 - - MOVQ SI, BX - ANDQ $7, BX - JZ aligned - - // Process the first few bytes to 8-byte align the input. - - // BX = 8 - BX. We need to process this many bytes to align. - SUBQ $1, BX - XORQ $7, BX - - BTQ $0, BX - JNC align_2 - - CRC32B (SI), AX - DECQ CX - INCQ SI - -align_2: - BTQ $1, BX - JNC align_4 - - // CRC32W (SI), AX - BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 - - SUBQ $2, CX - ADDQ $2, SI - -align_4: - BTQ $2, BX - JNC aligned - - // CRC32L (SI), AX - BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 - - SUBQ $4, CX - ADDQ $4, SI - -aligned: - // The input is now 8-byte aligned and we can process 8-byte chunks. - CMPQ CX, $8 - JL less_than_8 - - CRC32Q (SI), AX - ADDQ $8, SI - SUBQ $8, CX - JMP aligned - -less_than_8: - // We may have some bytes left over; process 4 bytes, then 2, then 1. - BTQ $2, CX - JNC less_than_4 - - // CRC32L (SI), AX - BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 - ADDQ $4, SI - -less_than_4: - BTQ $1, CX - JNC less_than_2 - - // CRC32W (SI), AX - BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 - ADDQ $2, SI - -less_than_2: - BTQ $0, CX - JNC done - - CRC32B (SI), AX - -done: - MOVL AX, ret+32(FP) - RET - -// castagnoliSSE42Triple updates three (non-inverted) crcs with (24*rounds) -// bytes from each buffer. -// -// func castagnoliSSE42Triple( -// crc1, crc2, crc3 uint32, -// a, b, c []byte, -// rounds uint32, -// ) (retA uint32, retB uint32, retC uint32) -TEXT ·castagnoliSSE42Triple(SB), NOSPLIT, $0 - MOVL crcA+0(FP), AX - MOVL crcB+4(FP), CX - MOVL crcC+8(FP), DX - - MOVQ a+16(FP), R8 // data pointer - MOVQ b+40(FP), R9 // data pointer - MOVQ c+64(FP), R10 // data pointer - - MOVL rounds+88(FP), R11 - -loop: - CRC32Q (R8), AX - CRC32Q (R9), CX - CRC32Q (R10), DX - - CRC32Q 8(R8), AX - CRC32Q 8(R9), CX - CRC32Q 8(R10), DX - - CRC32Q 16(R8), AX - CRC32Q 16(R9), CX - CRC32Q 16(R10), DX - - ADDQ $24, R8 - ADDQ $24, R9 - ADDQ $24, R10 - - DECQ R11 - JNZ loop - - MOVL AX, retA+96(FP) - MOVL CX, retB+100(FP) - MOVL DX, retC+104(FP) - RET - -// func haveSSE42() bool -TEXT ·haveSSE42(SB), NOSPLIT, $0 - XORQ AX, AX - INCL AX - CPUID - SHRQ $20, CX - ANDQ $1, CX - MOVB CX, ret+0(FP) - RET - -// func haveCLMUL() bool -TEXT ·haveCLMUL(SB), NOSPLIT, $0 - XORQ AX, AX - INCL AX - CPUID - SHRQ $1, CX - ANDQ $1, CX - MOVB CX, ret+0(FP) - RET - -// func haveSSE41() bool -TEXT ·haveSSE41(SB), NOSPLIT, $0 - XORQ AX, AX - INCL AX - CPUID - SHRQ $19, CX - ANDQ $1, CX - MOVB CX, ret+0(FP) - RET - -// CRC32 polynomial data -// -// These constants are lifted from the -// Linux kernel, since they avoid the costly -// PSHUFB 16 byte reversal proposed in the -// original Intel paper. -DATA r2r1kp<>+0(SB)/8, $0x154442bd4 -DATA r2r1kp<>+8(SB)/8, $0x1c6e41596 -DATA r4r3kp<>+0(SB)/8, $0x1751997d0 -DATA r4r3kp<>+8(SB)/8, $0x0ccaa009e -DATA rupolykp<>+0(SB)/8, $0x1db710641 -DATA rupolykp<>+8(SB)/8, $0x1f7011641 -DATA r5kp<>+0(SB)/8, $0x163cd6124 - -GLOBL r2r1kp<>(SB), RODATA, $16 -GLOBL r4r3kp<>(SB), RODATA, $16 -GLOBL rupolykp<>(SB), RODATA, $16 -GLOBL r5kp<>(SB), RODATA, $8 - -// Based on http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf -// len(p) must be at least 64, and must be a multiple of 16. - -// func ieeeCLMUL(crc uint32, p []byte) uint32 -TEXT ·ieeeCLMUL(SB), NOSPLIT, $0 - MOVL crc+0(FP), X0 // Initial CRC value - MOVQ p+8(FP), SI // data pointer - MOVQ p_len+16(FP), CX // len(p) - - MOVOU (SI), X1 - MOVOU 16(SI), X2 - MOVOU 32(SI), X3 - MOVOU 48(SI), X4 - PXOR X0, X1 - ADDQ $64, SI // buf+=64 - SUBQ $64, CX // len-=64 - CMPQ CX, $64 // Less than 64 bytes left - JB remain64 - - MOVOA r2r1kp<>+0(SB), X0 - -loopback64: - MOVOA X1, X5 - MOVOA X2, X6 - MOVOA X3, X7 - MOVOA X4, X8 - - PCLMULQDQ $0, X0, X1 - PCLMULQDQ $0, X0, X2 - PCLMULQDQ $0, X0, X3 - PCLMULQDQ $0, X0, X4 - - // Load next early - MOVOU (SI), X11 - MOVOU 16(SI), X12 - MOVOU 32(SI), X13 - MOVOU 48(SI), X14 - - PCLMULQDQ $0x11, X0, X5 - PCLMULQDQ $0x11, X0, X6 - PCLMULQDQ $0x11, X0, X7 - PCLMULQDQ $0x11, X0, X8 - - PXOR X5, X1 - PXOR X6, X2 - PXOR X7, X3 - PXOR X8, X4 - - PXOR X11, X1 - PXOR X12, X2 - PXOR X13, X3 - PXOR X14, X4 - - ADDQ $0x40, DI - ADDQ $64, SI // buf+=64 - SUBQ $64, CX // len-=64 - CMPQ CX, $64 // Less than 64 bytes left? - JGE loopback64 - - // Fold result into a single register (X1) -remain64: - MOVOA r4r3kp<>+0(SB), X0 - - MOVOA X1, X5 - PCLMULQDQ $0, X0, X1 - PCLMULQDQ $0x11, X0, X5 - PXOR X5, X1 - PXOR X2, X1 - - MOVOA X1, X5 - PCLMULQDQ $0, X0, X1 - PCLMULQDQ $0x11, X0, X5 - PXOR X5, X1 - PXOR X3, X1 - - MOVOA X1, X5 - PCLMULQDQ $0, X0, X1 - PCLMULQDQ $0x11, X0, X5 - PXOR X5, X1 - PXOR X4, X1 - - // If there is less than 16 bytes left we are done - CMPQ CX, $16 - JB finish - - // Encode 16 bytes -remain16: - MOVOU (SI), X10 - MOVOA X1, X5 - PCLMULQDQ $0, X0, X1 - PCLMULQDQ $0x11, X0, X5 - PXOR X5, X1 - PXOR X10, X1 - SUBQ $16, CX - ADDQ $16, SI - CMPQ CX, $16 - JGE remain16 - -finish: - // Fold final result into 32 bits and return it - PCMPEQB X3, X3 - PCLMULQDQ $1, X1, X0 - PSRLDQ $8, X1 - PXOR X0, X1 - - MOVOA X1, X2 - MOVQ r5kp<>+0(SB), X0 - - // Creates 32 bit mask. Note that we don't care about upper half. - PSRLQ $32, X3 - - PSRLDQ $4, X2 - PAND X3, X1 - PCLMULQDQ $0, X0, X1 - PXOR X2, X1 - - MOVOA rupolykp<>+0(SB), X0 - - MOVOA X1, X2 - PAND X3, X1 - PCLMULQDQ $0x10, X0, X1 - PAND X3, X1 - PCLMULQDQ $0, X0, X1 - PXOR X2, X1 - - // PEXTRD $1, X1, AX (SSE 4.1) - BYTE $0x66; BYTE $0x0f; BYTE $0x3a - BYTE $0x16; BYTE $0xc8; BYTE $0x01 - MOVL AX, ret+32(FP) - - RET diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64p32.go b/vendor/github.com/klauspost/crc32/crc32_amd64p32.go deleted file mode 100644 index 3222b06..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_amd64p32.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2011 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. - -// +build !appengine,!gccgo - -package crc32 - -// This file contains the code to call the SSE 4.2 version of the Castagnoli -// CRC. - -// haveSSE42 is defined in crc32_amd64p32.s and uses CPUID to test for SSE 4.2 -// support. -func haveSSE42() bool - -// castagnoliSSE42 is defined in crc32_amd64p32.s and uses the SSE4.2 CRC32 -// instruction. -//go:noescape -func castagnoliSSE42(crc uint32, p []byte) uint32 - -var sse42 = haveSSE42() - -func archAvailableCastagnoli() bool { - return sse42 -} - -func archInitCastagnoli() { - if !sse42 { - panic("not available") - } - // No initialization necessary. -} - -func archUpdateCastagnoli(crc uint32, p []byte) uint32 { - if !sse42 { - panic("not available") - } - return castagnoliSSE42(crc, p) -} - -func archAvailableIEEE() bool { return false } -func archInitIEEE() { panic("not available") } -func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") } diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64p32.s b/vendor/github.com/klauspost/crc32/crc32_amd64p32.s deleted file mode 100644 index a578d68..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_amd64p32.s +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2011 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. - -// +build gc - -#define NOSPLIT 4 -#define RODATA 8 - -// func castagnoliSSE42(crc uint32, p []byte) uint32 -TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 - MOVL crc+0(FP), AX // CRC value - MOVL p+4(FP), SI // data pointer - MOVL p_len+8(FP), CX // len(p) - - NOTL AX - - // If there's less than 8 bytes to process, we do it byte-by-byte. - CMPQ CX, $8 - JL cleanup - - // Process individual bytes until the input is 8-byte aligned. -startup: - MOVQ SI, BX - ANDQ $7, BX - JZ aligned - - CRC32B (SI), AX - DECQ CX - INCQ SI - JMP startup - -aligned: - // The input is now 8-byte aligned and we can process 8-byte chunks. - CMPQ CX, $8 - JL cleanup - - CRC32Q (SI), AX - ADDQ $8, SI - SUBQ $8, CX - JMP aligned - -cleanup: - // We may have some bytes left over that we process one at a time. - CMPQ CX, $0 - JE done - - CRC32B (SI), AX - INCQ SI - DECQ CX - JMP cleanup - -done: - NOTL AX - MOVL AX, ret+16(FP) - RET - -// func haveSSE42() bool -TEXT ·haveSSE42(SB), NOSPLIT, $0 - XORQ AX, AX - INCL AX - CPUID - SHRQ $20, CX - ANDQ $1, CX - MOVB CX, ret+0(FP) - RET - diff --git a/vendor/github.com/klauspost/crc32/crc32_generic.go b/vendor/github.com/klauspost/crc32/crc32_generic.go deleted file mode 100644 index abacbb6..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_generic.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file contains CRC32 algorithms that are not specific to any architecture -// and don't use hardware acceleration. -// -// The simple (and slow) CRC32 implementation only uses a 256*4 bytes table. -// -// The slicing-by-8 algorithm is a faster implementation that uses a bigger -// table (8*256*4 bytes). - -package crc32 - -// simpleMakeTable allocates and constructs a Table for the specified -// polynomial. The table is suitable for use with the simple algorithm -// (simpleUpdate). -func simpleMakeTable(poly uint32) *Table { - t := new(Table) - simplePopulateTable(poly, t) - return t -} - -// simplePopulateTable constructs a Table for the specified polynomial, suitable -// for use with simpleUpdate. -func simplePopulateTable(poly uint32, t *Table) { - for i := 0; i < 256; i++ { - crc := uint32(i) - for j := 0; j < 8; j++ { - if crc&1 == 1 { - crc = (crc >> 1) ^ poly - } else { - crc >>= 1 - } - } - t[i] = crc - } -} - -// simpleUpdate uses the simple algorithm to update the CRC, given a table that -// was previously computed using simpleMakeTable. -func simpleUpdate(crc uint32, tab *Table, p []byte) uint32 { - crc = ^crc - for _, v := range p { - crc = tab[byte(crc)^v] ^ (crc >> 8) - } - return ^crc -} - -// Use slicing-by-8 when payload >= this value. -const slicing8Cutoff = 16 - -// slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm. -type slicing8Table [8]Table - -// slicingMakeTable constructs a slicing8Table for the specified polynomial. The -// table is suitable for use with the slicing-by-8 algorithm (slicingUpdate). -func slicingMakeTable(poly uint32) *slicing8Table { - t := new(slicing8Table) - simplePopulateTable(poly, &t[0]) - for i := 0; i < 256; i++ { - crc := t[0][i] - for j := 1; j < 8; j++ { - crc = t[0][crc&0xFF] ^ (crc >> 8) - t[j][i] = crc - } - } - return t -} - -// slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a -// table that was previously computed using slicingMakeTable. -func slicingUpdate(crc uint32, tab *slicing8Table, p []byte) uint32 { - if len(p) >= slicing8Cutoff { - crc = ^crc - for len(p) > 8 { - crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 - crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^ - tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^ - tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF] - p = p[8:] - } - crc = ^crc - } - if len(p) == 0 { - return crc - } - return simpleUpdate(crc, &tab[0], p) -} diff --git a/vendor/github.com/klauspost/crc32/crc32_otherarch.go b/vendor/github.com/klauspost/crc32/crc32_otherarch.go deleted file mode 100644 index cc96076..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_otherarch.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2011 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. - -// +build !amd64,!amd64p32,!s390x - -package crc32 - -func archAvailableIEEE() bool { return false } -func archInitIEEE() { panic("not available") } -func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") } - -func archAvailableCastagnoli() bool { return false } -func archInitCastagnoli() { panic("not available") } -func archUpdateCastagnoli(crc uint32, p []byte) uint32 { panic("not available") } diff --git a/vendor/github.com/klauspost/crc32/crc32_s390x.go b/vendor/github.com/klauspost/crc32/crc32_s390x.go deleted file mode 100644 index ce96f03..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_s390x.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x - -package crc32 - -const ( - vxMinLen = 64 - vxAlignMask = 15 // align to 16 bytes -) - -// hasVectorFacility reports whether the machine has the z/Architecture -// vector facility installed and enabled. -func hasVectorFacility() bool - -var hasVX = hasVectorFacility() - -// vectorizedCastagnoli implements CRC32 using vector instructions. -// It is defined in crc32_s390x.s. -//go:noescape -func vectorizedCastagnoli(crc uint32, p []byte) uint32 - -// vectorizedIEEE implements CRC32 using vector instructions. -// It is defined in crc32_s390x.s. -//go:noescape -func vectorizedIEEE(crc uint32, p []byte) uint32 - -func archAvailableCastagnoli() bool { - return hasVX -} - -var archCastagnoliTable8 *slicing8Table - -func archInitCastagnoli() { - if !hasVX { - panic("not available") - } - // We still use slicing-by-8 for small buffers. - archCastagnoliTable8 = slicingMakeTable(Castagnoli) -} - -// archUpdateCastagnoli calculates the checksum of p using -// vectorizedCastagnoli. -func archUpdateCastagnoli(crc uint32, p []byte) uint32 { - if !hasVX { - panic("not available") - } - // Use vectorized function if data length is above threshold. - if len(p) >= vxMinLen { - aligned := len(p) & ^vxAlignMask - crc = vectorizedCastagnoli(crc, p[:aligned]) - p = p[aligned:] - } - if len(p) == 0 { - return crc - } - return slicingUpdate(crc, archCastagnoliTable8, p) -} - -func archAvailableIEEE() bool { - return hasVX -} - -var archIeeeTable8 *slicing8Table - -func archInitIEEE() { - if !hasVX { - panic("not available") - } - // We still use slicing-by-8 for small buffers. - archIeeeTable8 = slicingMakeTable(IEEE) -} - -// archUpdateIEEE calculates the checksum of p using vectorizedIEEE. -func archUpdateIEEE(crc uint32, p []byte) uint32 { - if !hasVX { - panic("not available") - } - // Use vectorized function if data length is above threshold. - if len(p) >= vxMinLen { - aligned := len(p) & ^vxAlignMask - crc = vectorizedIEEE(crc, p[:aligned]) - p = p[aligned:] - } - if len(p) == 0 { - return crc - } - return slicingUpdate(crc, archIeeeTable8, p) -} diff --git a/vendor/github.com/klauspost/crc32/crc32_s390x.s b/vendor/github.com/klauspost/crc32/crc32_s390x.s deleted file mode 100644 index e980ca2..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_s390x.s +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x - -#include "textflag.h" - -// Vector register range containing CRC-32 constants - -#define CONST_PERM_LE2BE V9 -#define CONST_R2R1 V10 -#define CONST_R4R3 V11 -#define CONST_R5 V12 -#define CONST_RU_POLY V13 -#define CONST_CRC_POLY V14 - -// The CRC-32 constant block contains reduction constants to fold and -// process particular chunks of the input data stream in parallel. -// -// Note that the constant definitions below are extended in order to compute -// intermediate results with a single VECTOR GALOIS FIELD MULTIPLY instruction. -// The rightmost doubleword can be 0 to prevent contribution to the result or -// can be multiplied by 1 to perform an XOR without the need for a separate -// VECTOR EXCLUSIVE OR instruction. -// -// The polynomials used are bit-reflected: -// -// IEEE: P'(x) = 0x0edb88320 -// Castagnoli: P'(x) = 0x082f63b78 - -// IEEE polynomial constants -DATA ·crcleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask -DATA ·crcleconskp+8(SB)/8, $0x0706050403020100 -DATA ·crcleconskp+16(SB)/8, $0x00000001c6e41596 // R2 -DATA ·crcleconskp+24(SB)/8, $0x0000000154442bd4 // R1 -DATA ·crcleconskp+32(SB)/8, $0x00000000ccaa009e // R4 -DATA ·crcleconskp+40(SB)/8, $0x00000001751997d0 // R3 -DATA ·crcleconskp+48(SB)/8, $0x0000000000000000 -DATA ·crcleconskp+56(SB)/8, $0x0000000163cd6124 // R5 -DATA ·crcleconskp+64(SB)/8, $0x0000000000000000 -DATA ·crcleconskp+72(SB)/8, $0x00000001F7011641 // u' -DATA ·crcleconskp+80(SB)/8, $0x0000000000000000 -DATA ·crcleconskp+88(SB)/8, $0x00000001DB710641 // P'(x) << 1 - -GLOBL ·crcleconskp(SB), RODATA, $144 - -// Castagonli Polynomial constants -DATA ·crccleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask -DATA ·crccleconskp+8(SB)/8, $0x0706050403020100 -DATA ·crccleconskp+16(SB)/8, $0x000000009e4addf8 // R2 -DATA ·crccleconskp+24(SB)/8, $0x00000000740eef02 // R1 -DATA ·crccleconskp+32(SB)/8, $0x000000014cd00bd6 // R4 -DATA ·crccleconskp+40(SB)/8, $0x00000000f20c0dfe // R3 -DATA ·crccleconskp+48(SB)/8, $0x0000000000000000 -DATA ·crccleconskp+56(SB)/8, $0x00000000dd45aab8 // R5 -DATA ·crccleconskp+64(SB)/8, $0x0000000000000000 -DATA ·crccleconskp+72(SB)/8, $0x00000000dea713f1 // u' -DATA ·crccleconskp+80(SB)/8, $0x0000000000000000 -DATA ·crccleconskp+88(SB)/8, $0x0000000105ec76f0 // P'(x) << 1 - -GLOBL ·crccleconskp(SB), RODATA, $144 - -// func hasVectorFacility() bool -TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 - MOVD $x-24(SP), R1 - XC $24, 0(R1), 0(R1) // clear the storage - MOVD $2, R0 // R0 is the number of double words stored -1 - WORD $0xB2B01000 // STFLE 0(R1) - XOR R0, R0 // reset the value of R0 - MOVBZ z-8(SP), R1 - AND $0x40, R1 - BEQ novector - -vectorinstalled: - // check if the vector instruction has been enabled - VLEIB $0, $0xF, V16 - VLGVB $0, V16, R1 - CMPBNE R1, $0xF, novector - MOVB $1, ret+0(FP) // have vx - RET - -novector: - MOVB $0, ret+0(FP) // no vx - RET - -// The CRC-32 function(s) use these calling conventions: -// -// Parameters: -// -// R2: Initial CRC value, typically ~0; and final CRC (return) value. -// R3: Input buffer pointer, performance might be improved if the -// buffer is on a doubleword boundary. -// R4: Length of the buffer, must be 64 bytes or greater. -// -// Register usage: -// -// R5: CRC-32 constant pool base pointer. -// V0: Initial CRC value and intermediate constants and results. -// V1..V4: Data for CRC computation. -// V5..V8: Next data chunks that are fetched from the input buffer. -// -// V9..V14: CRC-32 constants. - -// func vectorizedIEEE(crc uint32, p []byte) uint32 -TEXT ·vectorizedIEEE(SB), NOSPLIT, $0 - MOVWZ crc+0(FP), R2 // R2 stores the CRC value - MOVD p+8(FP), R3 // data pointer - MOVD p_len+16(FP), R4 // len(p) - - MOVD $·crcleconskp(SB), R5 - BR vectorizedBody<>(SB) - -// func vectorizedCastagnoli(crc uint32, p []byte) uint32 -TEXT ·vectorizedCastagnoli(SB), NOSPLIT, $0 - MOVWZ crc+0(FP), R2 // R2 stores the CRC value - MOVD p+8(FP), R3 // data pointer - MOVD p_len+16(FP), R4 // len(p) - - // R5: crc-32 constant pool base pointer, constant is used to reduce crc - MOVD $·crccleconskp(SB), R5 - BR vectorizedBody<>(SB) - -TEXT vectorizedBody<>(SB), NOSPLIT, $0 - XOR $0xffffffff, R2 // NOTW R2 - VLM 0(R5), CONST_PERM_LE2BE, CONST_CRC_POLY - - // Load the initial CRC value into the rightmost word of V0 - VZERO V0 - VLVGF $3, R2, V0 - - // Crash if the input size is less than 64-bytes. - CMP R4, $64 - BLT crash - - // Load a 64-byte data chunk and XOR with CRC - VLM 0(R3), V1, V4 // 64-bytes into V1..V4 - - // Reflect the data if the CRC operation is in the bit-reflected domain - VPERM V1, V1, CONST_PERM_LE2BE, V1 - VPERM V2, V2, CONST_PERM_LE2BE, V2 - VPERM V3, V3, CONST_PERM_LE2BE, V3 - VPERM V4, V4, CONST_PERM_LE2BE, V4 - - VX V0, V1, V1 // V1 ^= CRC - ADD $64, R3 // BUF = BUF + 64 - ADD $(-64), R4 - - // Check remaining buffer size and jump to proper folding method - CMP R4, $64 - BLT less_than_64bytes - -fold_64bytes_loop: - // Load the next 64-byte data chunk into V5 to V8 - VLM 0(R3), V5, V8 - VPERM V5, V5, CONST_PERM_LE2BE, V5 - VPERM V6, V6, CONST_PERM_LE2BE, V6 - VPERM V7, V7, CONST_PERM_LE2BE, V7 - VPERM V8, V8, CONST_PERM_LE2BE, V8 - - // Perform a GF(2) multiplication of the doublewords in V1 with - // the reduction constants in V0. The intermediate result is - // then folded (accumulated) with the next data chunk in V5 and - // stored in V1. Repeat this step for the register contents - // in V2, V3, and V4 respectively. - - VGFMAG CONST_R2R1, V1, V5, V1 - VGFMAG CONST_R2R1, V2, V6, V2 - VGFMAG CONST_R2R1, V3, V7, V3 - VGFMAG CONST_R2R1, V4, V8, V4 - - // Adjust buffer pointer and length for next loop - ADD $64, R3 // BUF = BUF + 64 - ADD $(-64), R4 // LEN = LEN - 64 - - CMP R4, $64 - BGE fold_64bytes_loop - -less_than_64bytes: - // Fold V1 to V4 into a single 128-bit value in V1 - VGFMAG CONST_R4R3, V1, V2, V1 - VGFMAG CONST_R4R3, V1, V3, V1 - VGFMAG CONST_R4R3, V1, V4, V1 - - // Check whether to continue with 64-bit folding - CMP R4, $16 - BLT final_fold - -fold_16bytes_loop: - VL 0(R3), V2 // Load next data chunk - VPERM V2, V2, CONST_PERM_LE2BE, V2 - - VGFMAG CONST_R4R3, V1, V2, V1 // Fold next data chunk - - // Adjust buffer pointer and size for folding next data chunk - ADD $16, R3 - ADD $-16, R4 - - // Process remaining data chunks - CMP R4, $16 - BGE fold_16bytes_loop - -final_fold: - VLEIB $7, $0x40, V9 - VSRLB V9, CONST_R4R3, V0 - VLEIG $0, $1, V0 - - VGFMG V0, V1, V1 - - VLEIB $7, $0x20, V9 // Shift by words - VSRLB V9, V1, V2 // Store remaining bits in V2 - VUPLLF V1, V1 // Split rightmost doubleword - VGFMAG CONST_R5, V1, V2, V1 // V1 = (V1 * R5) XOR V2 - - // The input values to the Barret reduction are the degree-63 polynomial - // in V1 (R(x)), degree-32 generator polynomial, and the reduction - // constant u. The Barret reduction result is the CRC value of R(x) mod - // P(x). - // - // The Barret reduction algorithm is defined as: - // - // 1. T1(x) = floor( R(x) / x^32 ) GF2MUL u - // 2. T2(x) = floor( T1(x) / x^32 ) GF2MUL P(x) - // 3. C(x) = R(x) XOR T2(x) mod x^32 - // - // Note: To compensate the division by x^32, use the vector unpack - // instruction to move the leftmost word into the leftmost doubleword - // of the vector register. The rightmost doubleword is multiplied - // with zero to not contribute to the intermedate results. - - // T1(x) = floor( R(x) / x^32 ) GF2MUL u - VUPLLF V1, V2 - VGFMG CONST_RU_POLY, V2, V2 - - // Compute the GF(2) product of the CRC polynomial in VO with T1(x) in - // V2 and XOR the intermediate result, T2(x), with the value in V1. - // The final result is in the rightmost word of V2. - - VUPLLF V2, V2 - VGFMAG CONST_CRC_POLY, V2, V1, V2 - -done: - VLGVF $2, V2, R2 - XOR $0xffffffff, R2 // NOTW R2 - MOVWZ R2, ret + 32(FP) - RET - -crash: - MOVD $0, (R0) // input size is less than 64-bytes diff --git a/vendor/github.com/klauspost/crc32/crc32_test.go b/vendor/github.com/klauspost/crc32/crc32_test.go deleted file mode 100644 index 0399436..0000000 --- a/vendor/github.com/klauspost/crc32/crc32_test.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package crc32 - -import ( - crand "crypto/rand" - "hash" - mrand "math/rand" - "testing" -) - -type test struct { - ieee, castagnoli uint32 - in string -} - -var golden = []test{ - {0x0, 0x0, ""}, - {0xe8b7be43, 0xc1d04330, "a"}, - {0x9e83486d, 0xe2a22936, "ab"}, - {0x352441c2, 0x364b3fb7, "abc"}, - {0xed82cd11, 0x92c80a31, "abcd"}, - {0x8587d865, 0xc450d697, "abcde"}, - {0x4b8e39ef, 0x53bceff1, "abcdef"}, - {0x312a6aa6, 0xe627f441, "abcdefg"}, - {0xaeef2a50, 0xa9421b7, "abcdefgh"}, - {0x8da988af, 0x2ddc99fc, "abcdefghi"}, - {0x3981703a, 0xe6599437, "abcdefghij"}, - {0x6b9cdfe7, 0xb2cc01fe, "Discard medicine more than two years old."}, - {0xc90ef73f, 0xe28207f, "He who has a shady past knows that nice guys finish last."}, - {0xb902341f, 0xbe93f964, "I wouldn't marry him with a ten foot pole."}, - {0x42080e8, 0x9e3be0c3, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, - {0x154c6d11, 0xf505ef04, "The days of the digital watch are numbered. -Tom Stoppard"}, - {0x4c418325, 0x85d3dc82, "Nepal premier won't resign."}, - {0x33955150, 0xc5142380, "For every action there is an equal and opposite government program."}, - {0x26216a4b, 0x75eb77dd, "His money is twice tainted: 'taint yours and 'taint mine."}, - {0x1abbe45e, 0x91ebe9f7, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, - {0xc89a94f7, 0xf0b1168e, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, - {0xab3abe14, 0x572b74e2, "size: a.out: bad magic"}, - {0xbab102b6, 0x8a58a6d5, "The major problem is with sendmail. -Mark Horton"}, - {0x999149d7, 0x9c426c50, "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, - {0x6d52a33c, 0x735400a4, "If the enemy is within range, then so are you."}, - {0x90631e8d, 0xbec49c95, "It's well we cannot hear the screams/That we create in others' dreams."}, - {0x78309130, 0xa95a2079, "You remind me of a TV show, but that's all right: I watch it anyway."}, - {0x7d0a377f, 0xde2e65c5, "C is as portable as Stonehedge!!"}, - {0x8c79fd79, 0x297a88ed, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, - {0xa20b7167, 0x66ed1d8b, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, - {0x8e0bb443, 0xdcded527, "How can you write a big system without C++? -Paul Glick"}, -} - -// testGoldenIEEE verifies that the given function returns -// correct IEEE checksums. -func testGoldenIEEE(t *testing.T, crcFunc func(b []byte) uint32) { - for _, g := range golden { - if crc := crcFunc([]byte(g.in)); crc != g.ieee { - t.Errorf("IEEE(%s) = 0x%x want 0x%x", g.in, crc, g.ieee) - } - } -} - -// testGoldenCastagnoli verifies that the given function returns -// correct IEEE checksums. -func testGoldenCastagnoli(t *testing.T, crcFunc func(b []byte) uint32) { - for _, g := range golden { - if crc := crcFunc([]byte(g.in)); crc != g.castagnoli { - t.Errorf("Castagnoli(%s) = 0x%x want 0x%x", g.in, crc, g.castagnoli) - } - } -} - -// testCrossCheck generates random buffers of various lengths and verifies that -// the two "update" functions return the same result. -func testCrossCheck(t *testing.T, crcFunc1, crcFunc2 func(crc uint32, b []byte) uint32) { - // The AMD64 implementation has some cutoffs at lengths 168*3=504 and - // 1344*3=4032. We should make sure lengths around these values are in the - // list. - lengths := []int{0, 1, 2, 3, 4, 5, 10, 16, 50, 100, 128, - 500, 501, 502, 503, 504, 505, 512, 1000, 1024, 2000, - 4030, 4031, 4032, 4033, 4036, 4040, 4048, 4096, 5000, 10000} - for _, length := range lengths { - p := make([]byte, length) - _, _ = crand.Read(p) - crcInit := uint32(mrand.Int63()) - crc1 := crcFunc1(crcInit, p) - crc2 := crcFunc2(crcInit, p) - if crc1 != crc2 { - t.Errorf("mismatch: 0x%x vs 0x%x (buffer length %d)", crc1, crc2, length) - } - } -} - -// TestSimple tests the simple generic algorithm. -func TestSimple(t *testing.T) { - tab := simpleMakeTable(IEEE) - testGoldenIEEE(t, func(b []byte) uint32 { - return simpleUpdate(0, tab, b) - }) - - tab = simpleMakeTable(Castagnoli) - testGoldenCastagnoli(t, func(b []byte) uint32 { - return simpleUpdate(0, tab, b) - }) -} - -// TestSimple tests the slicing-by-8 algorithm. -func TestSlicing(t *testing.T) { - tab := slicingMakeTable(IEEE) - testGoldenIEEE(t, func(b []byte) uint32 { - return slicingUpdate(0, tab, b) - }) - - tab = slicingMakeTable(Castagnoli) - testGoldenCastagnoli(t, func(b []byte) uint32 { - return slicingUpdate(0, tab, b) - }) - - // Cross-check various polys against the simple algorithm. - for _, poly := range []uint32{IEEE, Castagnoli, Koopman, 0xD5828281} { - t1 := simpleMakeTable(poly) - f1 := func(crc uint32, b []byte) uint32 { - return simpleUpdate(crc, t1, b) - } - t2 := slicingMakeTable(poly) - f2 := func(crc uint32, b []byte) uint32 { - return slicingUpdate(crc, t2, b) - } - testCrossCheck(t, f1, f2) - } -} - -func TestArchIEEE(t *testing.T) { - if !archAvailableIEEE() { - t.Skip("Arch-specific IEEE not available.") - } - archInitIEEE() - slicingTable := slicingMakeTable(IEEE) - testCrossCheck(t, archUpdateIEEE, func(crc uint32, b []byte) uint32 { - return slicingUpdate(crc, slicingTable, b) - }) -} - -func TestArchCastagnoli(t *testing.T) { - if !archAvailableCastagnoli() { - t.Skip("Arch-specific Castagnoli not available.") - } - archInitCastagnoli() - slicingTable := slicingMakeTable(Castagnoli) - testCrossCheck(t, archUpdateCastagnoli, func(crc uint32, b []byte) uint32 { - return slicingUpdate(crc, slicingTable, b) - }) -} - -func TestGolden(t *testing.T) { - testGoldenIEEE(t, ChecksumIEEE) - - // Some implementations have special code to deal with misaligned - // data; test that as well. - for delta := 1; delta <= 7; delta++ { - testGoldenIEEE(t, func(b []byte) uint32 { - ieee := NewIEEE() - d := delta - if d >= len(b) { - d = len(b) - } - ieee.Write(b[:d]) - ieee.Write(b[d:]) - return ieee.Sum32() - }) - } - - castagnoliTab := MakeTable(Castagnoli) - if castagnoliTab == nil { - t.Errorf("nil Castagnoli Table") - } - - testGoldenCastagnoli(t, func(b []byte) uint32 { - castagnoli := New(castagnoliTab) - castagnoli.Write(b) - return castagnoli.Sum32() - }) - - // Some implementations have special code to deal with misaligned - // data; test that as well. - for delta := 1; delta <= 7; delta++ { - testGoldenCastagnoli(t, func(b []byte) uint32 { - castagnoli := New(castagnoliTab) - d := delta - if d >= len(b) { - d = len(b) - } - castagnoli.Write(b[:d]) - castagnoli.Write(b[d:]) - return castagnoli.Sum32() - }) - } -} - -func BenchmarkIEEECrc40B(b *testing.B) { - benchmark(b, NewIEEE(), 40, 0) -} - -func BenchmarkIEEECrc1KB(b *testing.B) { - benchmark(b, NewIEEE(), 1<<10, 0) -} - -func BenchmarkIEEECrc4KB(b *testing.B) { - benchmark(b, NewIEEE(), 4<<10, 0) -} - -func BenchmarkIEEECrc32KB(b *testing.B) { - benchmark(b, NewIEEE(), 32<<10, 0) -} - -func BenchmarkCastagnoliCrc15B(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 15, 0) -} - -func BenchmarkCastagnoliCrc15BMisaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 15, 1) -} - -func BenchmarkCastagnoliCrc40B(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 40, 0) -} - -func BenchmarkCastagnoliCrc40BMisaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 40, 1) -} - -func BenchmarkCastagnoliCrc512(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 512, 0) -} - -func BenchmarkCastagnoliCrc512Misaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 512, 1) -} - -func BenchmarkCastagnoliCrc1KB(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 0) -} - -func BenchmarkCastagnoliCrc1KBMisaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 1) -} - -func BenchmarkCastagnoliCrc4KB(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 0) -} - -func BenchmarkCastagnoliCrc4KBMisaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 1) -} - -func BenchmarkCastagnoliCrc32KB(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 0) -} - -func BenchmarkCastagnoliCrc32KBMisaligned(b *testing.B) { - benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 1) -} - -func benchmark(b *testing.B, h hash.Hash32, n, alignment int64) { - b.SetBytes(n) - data := make([]byte, n+alignment) - data = data[alignment:] - for i := range data { - data[i] = byte(i) - } - in := make([]byte, 0, h.Size()) - - // Warm up - h.Reset() - h.Write(data) - h.Sum(in) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - h.Reset() - h.Write(data) - h.Sum(in) - } -} diff --git a/vendor/github.com/klauspost/crc32/example_test.go b/vendor/github.com/klauspost/crc32/example_test.go deleted file mode 100644 index 621bf83..0000000 --- a/vendor/github.com/klauspost/crc32/example_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package crc32_test - -import ( - "fmt" - "hash/crc32" -) - -func ExampleMakeTable() { - // In this package, the CRC polynomial is represented in reversed notation, - // or LSB-first representation. - // - // LSB-first representation is a hexadecimal number with n bits, in which the - // most significant bit represents the coefficient of x⁰ and the least significant - // bit represents the coefficient of xⁿ⁻¹ (the coefficient for xⁿ is implicit). - // - // For example, CRC32-Q, as defined by the following polynomial, - // x³²+ x³¹+ x²⁴+ x²²+ x¹⁶+ x¹⁴+ x⁸+ x⁷+ x⁵+ x³+ x¹+ x⁰ - // has the reversed notation 0b11010101100000101000001010000001, so the value - // that should be passed to MakeTable is 0xD5828281. - crc32q := crc32.MakeTable(0xD5828281) - fmt.Printf("%08x\n", crc32.Checksum([]byte("Hello world"), crc32q)) - // Output: - // 2964d064 -} diff --git a/vendor/github.com/lib/pq/.travis.sh b/vendor/github.com/lib/pq/.travis.sh index ead01df..a297dc4 100755 --- a/vendor/github.com/lib/pq/.travis.sh +++ b/vendor/github.com/lib/pq/.travis.sh @@ -71,12 +71,6 @@ postgresql_uninstall() { } megacheck_install() { - # Megacheck is Go 1.6+, so skip if Go 1.5. - if [[ "$(go version)" =~ "go1.5" ]] - then - echo "megacheck not supported, skipping installation" - return 0 - fi # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous # new error messages in old code. go get -d honnef.co/go/tools/... @@ -86,12 +80,6 @@ megacheck_install() { } golint_install() { - # Golint is Go 1.6+, so skip if Go 1.5. - if [[ "$(go version)" =~ "go1.5" ]] - then - echo "golint not supported, skipping installation" - return 0 - fi go get github.com/golang/lint/golint } diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml index 4e34e88..18556e0 100644 --- a/vendor/github.com/lib/pq/.travis.yml +++ b/vendor/github.com/lib/pq/.travis.yml @@ -1,11 +1,9 @@ language: go go: - - 1.5.x - - 1.6.x - - 1.7.x - 1.8.x - 1.9.x + - 1.10.x - master sudo: true @@ -16,7 +14,7 @@ env: - PQGOSSLTESTS=1 - PQSSLCERTTEST_PATH=$PWD/certs - PGHOST=127.0.0.1 - - MEGACHECK_VERSION=2017.2.1 + - MEGACHECK_VERSION=2017.2.2 matrix: - PGVERSION=10 - PGVERSION=9.6 @@ -46,13 +44,7 @@ script: - > goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' - go vet ./... - # For compatibility with Go 1.5, launch only if megacheck is present. - - > - which megacheck > /dev/null && megacheck -go 1.5 ./... - || echo 'megacheck is not supported, skipping check' - # For compatibility with Go 1.5, launch only if golint is present. - - > - which golint > /dev/null && golint ./... - || echo 'golint is not supported, skipping check' + - megacheck -go 1.8 ./... + - golint ./... - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md index 781c89e..d71f3c2 100644 --- a/vendor/github.com/lib/pq/README.md +++ b/vendor/github.com/lib/pq/README.md @@ -14,18 +14,7 @@ documentation at . ## Tests -`go test` is used for testing. A running PostgreSQL server is -required, with the ability to log in. The default database to connect -to test with is "pqgotest," but it can be overridden using environment -variables. - -Example: - - PGHOST=/run/postgresql go test github.com/lib/pq - -Optionally, a benchmark suite can be run as part of the tests: - - PGHOST=/run/postgresql go test -bench . +`go test` is used for testing. See [TESTS.md](TESTS.md) for more details. ## Features diff --git a/vendor/github.com/lib/pq/TESTS.md b/vendor/github.com/lib/pq/TESTS.md new file mode 100644 index 0000000..f050211 --- /dev/null +++ b/vendor/github.com/lib/pq/TESTS.md @@ -0,0 +1,33 @@ +# Tests + +## Running Tests + +`go test` is used for testing. A running PostgreSQL +server is required, with the ability to log in. The +database to connect to test with is "pqgotest," on +"localhost" but these can be overridden using [environment +variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html). + +Example: + + PGHOST=/run/postgresql go test + +## Benchmarks + +A benchmark suite can be run as part of the tests: + + go test -bench . + +## Example setup (Docker) + +Run a postgres container: + +``` +docker run --expose 5432:5432 postgres +``` + +Run tests: + +``` +PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test +``` diff --git a/vendor/github.com/lib/pq/bench_test.go b/vendor/github.com/lib/pq/bench_test.go index e71f41d..33d7a02 100644 --- a/vendor/github.com/lib/pq/bench_test.go +++ b/vendor/github.com/lib/pq/bench_test.go @@ -5,6 +5,7 @@ package pq import ( "bufio" "bytes" + "context" "database/sql" "database/sql/driver" "io" @@ -156,7 +157,7 @@ func benchMockQuery(b *testing.B, c *conn, query string) { b.Fatal(err) } defer stmt.Close() - rows, err := stmt.Query(nil) + rows, err := stmt.(driver.StmtQueryContext).QueryContext(context.Background(), nil) if err != nil { b.Fatal(err) } @@ -266,7 +267,7 @@ func BenchmarkMockPreparedSelectSeries(b *testing.B) { } func benchPreparedMockQuery(b *testing.B, c *conn, stmt driver.Stmt) { - rows, err := stmt.Query(nil) + rows, err := stmt.(driver.StmtQueryContext).QueryContext(context.Background(), nil) if err != nil { b.Fatal(err) } diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index fadb88e..43c8df2 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -339,7 +339,20 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if err != nil { return nil, err } - cn.ssl(o) + + err = cn.ssl(o) + if err != nil { + return nil, err + } + + // cn.startup panics on error. Make sure we don't leak cn.c. + panicking := true + defer func() { + if panicking { + cn.c.Close() + } + }() + cn.buf = bufio.NewReader(cn.c) cn.startup(o) @@ -347,6 +360,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if timeout, ok := o["connect_timeout"]; ok && timeout != "0" { err = cn.c.SetDeadline(time.Time{}) } + panicking = false return cn, err } @@ -1019,30 +1033,35 @@ func (cn *conn) recv1() (t byte, r *readBuf) { return t, r } -func (cn *conn) ssl(o values) { - upgrade := ssl(o) +func (cn *conn) ssl(o values) error { + upgrade, err := ssl(o) + if err != nil { + return err + } + if upgrade == nil { // Nothing to do - return + return nil } w := cn.writeBuf(0) w.int32(80877103) - if err := cn.sendStartupPacket(w); err != nil { - panic(err) + if err = cn.sendStartupPacket(w); err != nil { + return err } b := cn.scratch[:1] - _, err := io.ReadFull(cn.c, b) + _, err = io.ReadFull(cn.c, b) if err != nil { - panic(err) + return err } if b[0] != 'S' { - panic(ErrSSLNotSupported) + return ErrSSLNotSupported } - cn.c = upgrade(cn.c) + cn.c, err = upgrade(cn.c) + return err } // isDriverSetting returns true iff a setting is purely for configuring the diff --git a/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go index ab97a10..a5254f2 100644 --- a/vendor/github.com/lib/pq/conn_go18.go +++ b/vendor/github.com/lib/pq/conn_go18.go @@ -108,7 +108,10 @@ func (cn *conn) cancel() error { can := conn{ c: c, } - can.ssl(cn.opts) + err = can.ssl(cn.opts) + if err != nil { + return err + } w := can.writeBuf(0) w.int32(80877102) // cancel request code diff --git a/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go index 030a798..e654b85 100644 --- a/vendor/github.com/lib/pq/conn_test.go +++ b/vendor/github.com/lib/pq/conn_test.go @@ -1,6 +1,7 @@ package pq import ( + "context" "database/sql" "database/sql/driver" "fmt" @@ -28,7 +29,7 @@ func forceBinaryParameters() bool { } } -func openTestConnConninfo(conninfo string) (*sql.DB, error) { +func testConninfo(conninfo string) string { defaultTo := func(envvar string, value string) { if os.Getenv(envvar) == "" { os.Setenv(envvar, value) @@ -43,8 +44,11 @@ func openTestConnConninfo(conninfo string) (*sql.DB, error) { !strings.HasPrefix(conninfo, "postgresql://") { conninfo = conninfo + " binary_parameters=yes" } + return conninfo +} - return sql.Open("postgres", conninfo) +func openTestConnConninfo(conninfo string) (*sql.DB, error) { + return sql.Open("postgres", testConninfo(conninfo)) } func openTestConn(t Fatalistic) *sql.DB { @@ -637,6 +641,57 @@ func TestErrorDuringStartup(t *testing.T) { } } +type testConn struct { + closed bool + net.Conn +} + +func (c *testConn) Close() error { + c.closed = true + return c.Conn.Close() +} + +type testDialer struct { + conns []*testConn +} + +func (d *testDialer) Dial(ntw, addr string) (net.Conn, error) { + c, err := net.Dial(ntw, addr) + if err != nil { + return nil, err + } + tc := &testConn{Conn: c} + d.conns = append(d.conns, tc) + return tc, nil +} + +func (d *testDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { + c, err := net.DialTimeout(ntw, addr, timeout) + if err != nil { + return nil, err + } + tc := &testConn{Conn: c} + d.conns = append(d.conns, tc) + return tc, nil +} + +func TestErrorDuringStartupClosesConn(t *testing.T) { + // Don't use the normal connection setup, this is intended to + // blow up in the startup packet from a non-existent user. + var d testDialer + c, err := DialOpen(&d, testConninfo("user=thisuserreallydoesntexist")) + if err == nil { + c.Close() + t.Fatal("expected dial error") + } + if len(d.conns) != 1 { + t.Fatalf("got len(d.conns) = %d, want = %d", len(d.conns), 1) + } + if !d.conns[0].closed { + t.Error("connection leaked") + } +} + func TestBadConn(t *testing.T) { var err error @@ -1209,8 +1264,8 @@ func TestParseComplete(t *testing.T) { // Test interface conformance. var ( - _ driver.Execer = (*conn)(nil) - _ driver.Queryer = (*conn)(nil) + _ driver.ExecerContext = (*conn)(nil) + _ driver.QueryerContext = (*conn)(nil) ) func TestNullAfterNonNull(t *testing.T) { @@ -1555,10 +1610,10 @@ func TestRowsResultTag(t *testing.T) { t.Fatal(err) } defer conn.Close() - q := conn.(driver.Queryer) + q := conn.(driver.QueryerContext) for _, test := range tests { - if rows, err := q.Query(test.query, nil); err != nil { + if rows, err := q.QueryContext(context.Background(), test.query, nil); err != nil { t.Fatalf("%s: %s", test.query, err) } else { r := rows.(ResultTag) diff --git a/vendor/github.com/lib/pq/connector.go b/vendor/github.com/lib/pq/connector.go new file mode 100644 index 0000000..9e66eb5 --- /dev/null +++ b/vendor/github.com/lib/pq/connector.go @@ -0,0 +1,43 @@ +// +build go1.10 + +package pq + +import ( + "context" + "database/sql/driver" +) + +// Connector represents a fixed configuration for the pq driver with a given +// name. Connector satisfies the database/sql/driver Connector interface and +// can be used to create any number of DB Conn's via the database/sql OpenDB +// function. +// +// See https://golang.org/pkg/database/sql/driver/#Connector. +// See https://golang.org/pkg/database/sql/#OpenDB. +type connector struct { + name string +} + +// Connect returns a connection to the database using the fixed configuration +// of this Connector. Context is not used. +func (c *connector) Connect(_ context.Context) (driver.Conn, error) { + return (&Driver{}).Open(c.name) +} + +// Driver returnst the underlying driver of this Connector. +func (c *connector) Driver() driver.Driver { + return &Driver{} +} + +var _ driver.Connector = &connector{} + +// NewConnector returns a connector for the pq driver in a fixed configuration +// with the given name. The returned connector can be used to create any number +// of equivalent Conn's. The returned connector is intended to be used with +// database/sql.OpenDB. +// +// See https://golang.org/pkg/database/sql/driver/#Connector. +// See https://golang.org/pkg/database/sql/#OpenDB. +func NewConnector(name string) (driver.Connector, error) { + return &connector{name: name}, nil +} diff --git a/vendor/github.com/lib/pq/connector_example_test.go b/vendor/github.com/lib/pq/connector_example_test.go new file mode 100644 index 0000000..5b66cf4 --- /dev/null +++ b/vendor/github.com/lib/pq/connector_example_test.go @@ -0,0 +1,33 @@ +// +build go1.10 + +package pq_test + +import ( + "database/sql" + "fmt" + + "github.com/lib/pq" +) + +func ExampleNewConnector() { + name := "" + connector, err := pq.NewConnector(name) + if err != nil { + fmt.Println(err) + return + } + db := sql.OpenDB(connector) + if err != nil { + fmt.Println(err) + return + } + defer db.Close() + + // Use the DB + txn, err := db.Begin() + if err != nil { + fmt.Println(err) + return + } + txn.Rollback() +} diff --git a/vendor/github.com/lib/pq/connector_test.go b/vendor/github.com/lib/pq/connector_test.go new file mode 100644 index 0000000..3d2c67b --- /dev/null +++ b/vendor/github.com/lib/pq/connector_test.go @@ -0,0 +1,67 @@ +// +build go1.10 + +package pq + +import ( + "context" + "database/sql" + "database/sql/driver" + "testing" +) + +func TestNewConnector_WorksWithOpenDB(t *testing.T) { + name := "" + c, err := NewConnector(name) + if err != nil { + t.Fatal(err) + } + db := sql.OpenDB(c) + defer db.Close() + // database/sql might not call our Open at all unless we do something with + // the connection + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + txn.Rollback() +} + +func TestNewConnector_Connect(t *testing.T) { + name := "" + c, err := NewConnector(name) + if err != nil { + t.Fatal(err) + } + db, err := c.Connect(context.Background()) + if err != nil { + t.Fatal(err) + } + defer db.Close() + // database/sql might not call our Open at all unless we do something with + // the connection + txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{}) + if err != nil { + t.Fatal(err) + } + txn.Rollback() +} + +func TestNewConnector_Driver(t *testing.T) { + name := "" + c, err := NewConnector(name) + if err != nil { + t.Fatal(err) + } + db, err := c.Driver().Open(name) + if err != nil { + t.Fatal(err) + } + defer db.Close() + // database/sql might not call our Open at all unless we do something with + // the connection + txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{}) + if err != nil { + t.Fatal(err) + } + txn.Rollback() +} diff --git a/vendor/github.com/lib/pq/copy_test.go b/vendor/github.com/lib/pq/copy_test.go index c1a3cd7..a888a89 100644 --- a/vendor/github.com/lib/pq/copy_test.go +++ b/vendor/github.com/lib/pq/copy_test.go @@ -4,6 +4,7 @@ import ( "bytes" "database/sql" "database/sql/driver" + "net" "strings" "testing" ) @@ -400,15 +401,19 @@ func TestCopyRespLoopConnectionError(t *testing.T) { if err == nil { t.Fatalf("expected error") } - pge, ok := err.(*Error) - if !ok { + switch pge := err.(type) { + case *Error: + if pge.Code.Name() != "admin_shutdown" { + t.Fatalf("expected admin_shutdown, got %s", pge.Code.Name()) + } + case *net.OpError: + // ignore + default: if err == driver.ErrBadConn { // likely an EPIPE } else { - t.Fatalf("expected *pq.Error or driver.ErrBadConn, got %+#v", err) + t.Fatalf("unexpected error, got %+#v", err) } - } else if pge.Code.Name() != "admin_shutdown" { - t.Fatalf("expected admin_shutdown, got %s", pge.Code.Name()) } _ = stmt.Close() diff --git a/vendor/github.com/lib/pq/encode_test.go b/vendor/github.com/lib/pq/encode_test.go index 634a05c..d58798a 100644 --- a/vendor/github.com/lib/pq/encode_test.go +++ b/vendor/github.com/lib/pq/encode_test.go @@ -4,7 +4,7 @@ import ( "bytes" "database/sql" "fmt" - "strings" + "regexp" "testing" "time" @@ -304,24 +304,27 @@ func TestInfinityTimestamp(t *testing.T) { var err error var resultT time.Time - expectedErrorStrPrefix := `sql: Scan error on column index 0: unsupported` + expectedErrorStrRegexp := regexp.MustCompile( + `^sql: Scan error on column index 0(, name "timestamp(tz)?"|): unsupported`) + type testCases []struct { - Query string - Param string - ExpectedErrStrPrefix string - ExpectedVal interface{} + Query string + Param string + ExpectedErrorStrRegexp *regexp.Regexp + ExpectedVal interface{} } tc := testCases{ - {"SELECT $1::timestamp", "-infinity", expectedErrorStrPrefix, "-infinity"}, - {"SELECT $1::timestamptz", "-infinity", expectedErrorStrPrefix, "-infinity"}, - {"SELECT $1::timestamp", "infinity", expectedErrorStrPrefix, "infinity"}, - {"SELECT $1::timestamptz", "infinity", expectedErrorStrPrefix, "infinity"}, + {"SELECT $1::timestamp", "-infinity", expectedErrorStrRegexp, "-infinity"}, + {"SELECT $1::timestamptz", "-infinity", expectedErrorStrRegexp, "-infinity"}, + {"SELECT $1::timestamp", "infinity", expectedErrorStrRegexp, "infinity"}, + {"SELECT $1::timestamptz", "infinity", expectedErrorStrRegexp, "infinity"}, } // try to assert []byte to time.Time for _, q := range tc { err = db.QueryRow(q.Query, q.Param).Scan(&resultT) - if !strings.HasPrefix(err.Error(), q.ExpectedErrStrPrefix) { - t.Errorf("Scanning -/+infinity, expected error to have prefix %q, got %q", q.ExpectedErrStrPrefix, err) + if !q.ExpectedErrorStrRegexp.MatchString(err.Error()) { + t.Errorf("Scanning -/+infinity, expected error to match regexp %q, got %q", + q.ExpectedErrorStrRegexp, err) } } // yield []byte diff --git a/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go index 6928d96..96aae29 100644 --- a/vendor/github.com/lib/pq/error.go +++ b/vendor/github.com/lib/pq/error.go @@ -460,6 +460,11 @@ func errorf(s string, args ...interface{}) { panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) } +// TODO(ainar-g) Rename to errorf after removing panics. +func fmterrorf(s string, args ...interface{}) error { + return fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)) +} + func errRecoverNoErrBadConn(err *error) { e := recover() if e == nil { @@ -488,7 +493,8 @@ func (c *conn) errRecover(err *error) { *err = v } case *net.OpError: - *err = driver.ErrBadConn + c.bad = true + *err = v case error: if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { *err = driver.ErrBadConn diff --git a/vendor/github.com/lib/pq/go18_test.go b/vendor/github.com/lib/pq/go18_test.go index 4bf6391..1a88a5b 100644 --- a/vendor/github.com/lib/pq/go18_test.go +++ b/vendor/github.com/lib/pq/go18_test.go @@ -228,7 +228,9 @@ func TestContextCancelBegin(t *testing.T) { cancel() if err != nil { t.Fatal(err) - } else if err := tx.Rollback(); err != nil && err != sql.ErrTxDone { + } else if err := tx.Rollback(); err != nil && + err.Error() != "pq: canceling statement due to user request" && + err != sql.ErrTxDone { t.Fatal(err) } }() diff --git a/vendor/github.com/lib/pq/notify.go b/vendor/github.com/lib/pq/notify.go index 412c6ac..947d189 100644 --- a/vendor/github.com/lib/pq/notify.go +++ b/vendor/github.com/lib/pq/notify.go @@ -637,7 +637,7 @@ func (l *Listener) disconnectCleanup() error { // after the connection has been established. func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notification) error { doneChan := make(chan error) - go func() { + go func(notificationChan <-chan *Notification) { for channel := range l.channels { // If we got a response, return that error to our caller as it's // going to be more descriptive than cn.Err(). @@ -658,7 +658,7 @@ func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notificatio } } doneChan <- nil - }() + }(notificationChan) // Ignore notifications while synchronization is going on to avoid // deadlocks. We have to send a nil notification over Notify anyway as @@ -784,7 +784,7 @@ func (l *Listener) listenerConnLoop() { } l.emitEvent(ListenerEventDisconnected, err) - time.Sleep(nextReconnect.Sub(time.Now())) + time.Sleep(time.Until(nextReconnect)) } } diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go index 7deb304..e1a326a 100644 --- a/vendor/github.com/lib/pq/ssl.go +++ b/vendor/github.com/lib/pq/ssl.go @@ -12,7 +12,7 @@ import ( // ssl generates a function to upgrade a net.Conn based on the "sslmode" and // related settings. The function is nil when no upgrade should take place. -func ssl(o values) func(net.Conn) net.Conn { +func ssl(o values) (func(net.Conn) (net.Conn, error), error) { verifyCaOnly := false tlsConf := tls.Config{} switch mode := o["sslmode"]; mode { @@ -45,29 +45,38 @@ func ssl(o values) func(net.Conn) net.Conn { case "verify-full": tlsConf.ServerName = o["host"] case "disable": - return nil + return nil, nil default: - errorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) + return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) } - sslClientCertificates(&tlsConf, o) - sslCertificateAuthority(&tlsConf, o) + err := sslClientCertificates(&tlsConf, o) + if err != nil { + return nil, err + } + err = sslCertificateAuthority(&tlsConf, o) + if err != nil { + return nil, err + } sslRenegotiation(&tlsConf) - return func(conn net.Conn) net.Conn { + return func(conn net.Conn) (net.Conn, error) { client := tls.Client(conn, &tlsConf) if verifyCaOnly { - sslVerifyCertificateAuthority(client, &tlsConf) + err := sslVerifyCertificateAuthority(client, &tlsConf) + if err != nil { + return nil, err + } } - return client - } + return client, nil + }, nil } // sslClientCertificates adds the certificate specified in the "sslcert" and // "sslkey" settings, or if they aren't set, from the .postgresql directory // in the user's home directory. The configured files must exist and have // the correct permissions. -func sslClientCertificates(tlsConf *tls.Config, o values) { +func sslClientCertificates(tlsConf *tls.Config, o values) error { // user.Current() might fail when cross-compiling. We have to ignore the // error and continue without home directory defaults, since we wouldn't // know from where to load them. @@ -82,13 +91,13 @@ func sslClientCertificates(tlsConf *tls.Config, o values) { } // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045 if len(sslcert) == 0 { - return + return nil } // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054 if _, err := os.Stat(sslcert); os.IsNotExist(err) { - return + return nil } else if err != nil { - panic(err) + return err } // In libpq, the ssl key is only loaded if the setting is not blank. @@ -101,19 +110,21 @@ func sslClientCertificates(tlsConf *tls.Config, o values) { if len(sslkey) > 0 { if err := sslKeyPermissions(sslkey); err != nil { - panic(err) + return err } } cert, err := tls.LoadX509KeyPair(sslcert, sslkey) if err != nil { - panic(err) + return err } + tlsConf.Certificates = []tls.Certificate{cert} + return nil } // sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. -func sslCertificateAuthority(tlsConf *tls.Config, o values) { +func sslCertificateAuthority(tlsConf *tls.Config, o values) error { // In libpq, the root certificate is only loaded if the setting is not blank. // // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951 @@ -122,22 +133,24 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) { cert, err := ioutil.ReadFile(sslrootcert) if err != nil { - panic(err) + return err } if !tlsConf.RootCAs.AppendCertsFromPEM(cert) { - errorf("couldn't parse pem in sslrootcert") + return fmterrorf("couldn't parse pem in sslrootcert") } } + + return nil } // sslVerifyCertificateAuthority carries out a TLS handshake to the server and // verifies the presented certificate against the CA, i.e. the one specified in // sslrootcert or the system CA if sslrootcert was not specified. -func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { +func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) error { err := client.Handshake() if err != nil { - panic(err) + return err } certs := client.ConnectionState().PeerCertificates opts := x509.VerifyOptions{ @@ -152,7 +165,5 @@ func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) - if err != nil { - panic(err) - } + return err } diff --git a/vendor/github.com/mattn/go-sqlite3/.gitignore b/vendor/github.com/mattn/go-sqlite3/.gitignore index 8a0e48d..fa0e6b5 100644 --- a/vendor/github.com/mattn/go-sqlite3/.gitignore +++ b/vendor/github.com/mattn/go-sqlite3/.gitignore @@ -2,3 +2,13 @@ *.exe *.dll *.o + +# VSCode +.vscode + +# Exclude from upgrade +upgrade/*.c +upgrade/*.h + +# Exclude upgrade binary +upgrade/upgrade diff --git a/vendor/github.com/mattn/go-sqlite3/.travis.yml b/vendor/github.com/mattn/go-sqlite3/.travis.yml index 46e70cb..a21c817 100644 --- a/vendor/github.com/mattn/go-sqlite3/.travis.yml +++ b/vendor/github.com/mattn/go-sqlite3/.travis.yml @@ -1,19 +1,41 @@ language: go -sudo: required -dist: trusty + +os: + - linux + - osx + +addons: + apt: + update: true + env: - - GOTAGS= - - GOTAGS=libsqlite3 - - GOTAGS=trace - - GOTAGS=vtable + matrix: + - GOTAGS= + - GOTAGS=libsqlite3 + - GOTAGS="sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable" + - GOTAGS=sqlite_vacuum_full + go: - - 1.7.x - - 1.8.x - 1.9.x - - master + - 1.10.x + before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover + - | + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + brew update + brew upgrade icu4c + fi + - | + go get github.com/smartystreets/goconvey + if [[ "${GOOS}" != "windows" ]]; then + go get github.com/mattn/goveralls + go get golang.org/x/tools/cmd/cover + fi + script: - - $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx - - go test -race -v . -tags "$GOTAGS" + - GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) go build -v -tags "${GOTAGS}" . + - | + if [[ "${GOOS}" != "windows" ]]; then + $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx + go test -race -v . -tags "${GOTAGS}" + fi diff --git a/vendor/github.com/mattn/go-sqlite3/README.md b/vendor/github.com/mattn/go-sqlite3/README.md index ad00f10..37d017a 100644 --- a/vendor/github.com/mattn/go-sqlite3/README.md +++ b/vendor/github.com/mattn/go-sqlite3/README.md @@ -6,13 +6,43 @@ go-sqlite3 [![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3) -Description ------------ +# Description sqlite3 driver conforming to the built-in database/sql interface -Installation ------------- +Supported Golang version: +- 1.9.x +- 1.10.x + +[This package follows the official Golang Release Policy.](https://golang.org/doc/devel/release.html#policy) + +### Overview + +- [Installation](#installation) +- [API Reference](#api-reference) +- [Connection String](#connection-string) +- [Features](#features) +- [Compilation](#compilation) + - [Android](#android) + - [ARM](#arm) + - [Cross Compile](#cross-compile) + - [Google Cloud Platform](#google-cloud-platform) + - [Linux](#linux) + - [Alpine](#alpine) + - [Fedora](#fedora) + - [Ubuntu](#ubuntu) + - [Mac OSX](#mac-osx) + - [Windows](#windows) + - [Errors](#errors) +- [User Authentication](#user-authentication) + - [Compile](#compile) + - [Usage](#usage) +- [Extensions](#extensions) + - [Spatialite](#spatialite) +- [FAQ](#faq) +- [License](#license) + +# Installation This package can be installed with the go get command: @@ -20,70 +50,460 @@ This package can be installed with the go get command: _go-sqlite3_ is *cgo* package. If you want to build your app using go-sqlite3, you need gcc. -However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite3`, you don't need gcc to build your app anymore. +However, after you have built and installed _go-sqlite3_ with `go install github.com/mattn/go-sqlite3` (which requires gcc), you can build your app without relying on gcc in future. -Documentation -------------- +***Important: because this is a `CGO` enabled package you are required to set the environment variable `CGO_ENABLED=1` and have a `gcc` compile present within your path.*** + +# API Reference API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3 -Examples can be found under the `./_example` directory +Examples can be found under the [examples](./_example) directory -FAQ ---- +# Connection String -* Want to build go-sqlite3 with libsqlite3 on my linux. +When creating a new SQLite database or connection to an existing one, with the file name additional options can be given. +This is also known as a DSN string. (Data Source Name). - Use `go build --tags "libsqlite3 linux"` +Options are append after the filename of the SQLite database. +The database filename and options are seperated by an `?` (Question Mark). -* Want to build go-sqlite3 with libsqlite3 on OS X. +This also applies when using an in-memory database instead of a file. - Install sqlite3 from homebrew: `brew install sqlite3` +Options can be given using the following format: `KEYWORD=VALUE` and multiple options can be combined with the `&` ampersand. - Use `go build --tags "libsqlite3 darwin"` +This library supports dsn options of SQLite itself and provides additional options. -* Want to build go-sqlite3 with icu extension. +Boolean values can be one of: +* `0` `no` `false` `off` +* `1` `yes` `true` `on` - Use `go build --tags "icu"` +| Name | Key | Value(s) | Description | +|------|-----|----------|-------------| +| UA - Create | `_auth` | - | Create User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Username | `_auth_user` | `string` | Username for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Password | `_auth_pass` | `string` | Password for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Crypt | `_auth_crypt` |

  • SHA1
  • SSHA1
  • SHA256
  • SSHA256
  • SHA384
  • SSHA384
  • SHA512
  • SSHA512
| Password encoder to use for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Salt | `_auth_salt` | `string` | Salt to use if the configure password encoder requires a salt, for User Authentication, for more information see [User Authentication](#user-authentication) | +| Auto Vacuum | `_auto_vacuum` \| `_vacuum` |
  • `0` \| `none`
  • `1` \| `full`
  • `2` \| `incremental`
| For more information see [PRAGMA auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) | +| Busy Timeout | `_busy_timeout` \| `_timeout` | `int` | Specify value for sqlite3_busy_timeout. For more information see [PRAGMA busy_timeout](https://www.sqlite.org/pragma.html#pragma_busy_timeout) | +| Case Sensitive LIKE | `_case_sensitive_like` \| `_cslike` | `boolean` | For more information see [PRAGMA case_sensitive_like](https://www.sqlite.org/pragma.html#pragma_case_sensitive_like) | +| Defer Foreign Keys | `_defer_foreign_keys` \| `_defer_fk` | `boolean` | For more information see [PRAGMA defer_foreign_keys](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) | +| Foreign Keys | `_foreign_keys` \| `_fk` | `boolean` | For more information see [PRAGMA foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys) | +| Ignore CHECK Constraints | `_ignore_check_constraints` | `boolean` | For more information see [PRAGMA ignore_check_constraints](https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints) | +| Immutable | `immutable` | `boolean` | For more information see [Immutable](https://www.sqlite.org/c3ref/open.html) | +| Journal Mode | `_journal_mode` \| `_journal` |
  • DELETE
  • TRUNCATE
  • PERSIST
  • MEMORY
  • WAL
  • OFF
| For more information see [PRAGMA journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) | +| Locking Mode | `_locking_mode` \| `_locking` |
  • NORMAL
  • EXCLUSIVE
| For more information see [PRAGMA locking_mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) | +| Mode | `mode` |
  • ro
  • rw
  • rwc
  • memory
| Access Mode of the database. For more information see [SQLite Open](https://www.sqlite.org/c3ref/open.html) | +| Mutex Locking | `_mutex` |
  • no
  • full
| Specify mutex mode. | +| Query Only | `_query_only` | `boolean` | For more information see [PRAGMA query_only](https://www.sqlite.org/pragma.html#pragma_query_only) | +| Recursive Triggers | `_recursive_triggers` \| `_rt` | `boolean` | For more information see [PRAGMA recursive_triggers](https://www.sqlite.org/pragma.html#pragma_recursive_triggers) | +| Secure Delete | `_secure_delete` | `boolean` \| `FAST` | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | +| Shared-Cache Mode | `cache` |
  • shared
  • private
| Set cache mode for more information see [sqlite.org](https://www.sqlite.org/sharedcache.html) | +| Synchronous | `_synchronous` \| `_sync` |
  • 0 \| OFF
  • 1 \| NORMAL
  • 2 \| FULL
  • 3 \| EXTRA
| For more information see [PRAGMA synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) | +| Time Zone Location | `_loc` | auto | Specify location of time format. | +| Transaction Lock | `_txlock` |
  • immediate
  • deferred
  • exclusive
| Specify locking behavior for transactions. | +| Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. | - Available extensions: `json1`, `fts5`, `icu` +## DSN Examples -* Can't build go-sqlite3 on windows 64bit. +``` +file:test.db?cache=shared&mode=memory +``` + +# Features + +This package allows additional configuration of features available within SQLite3 to be enabled or disabled by golang build constraints also known as build `tags`. + +[Click here for more information about build tags / constraints.](https://golang.org/pkg/go/build/#hdr-Build_Constraints) + +### Usage + +If you wish to build this library with additional extensions / features. +Use the following command. + +```bash +go build --tags "" +``` + +For available features see the extension list. +When using multiple build tags, all the different tags should be space delimted. + +Example: + +```bash +go build --tags "icu json1 fts5 secure_delete" +``` + +### Feature / Extension List + +| Extension | Build Tag | Description | +|-----------|-----------|-------------| +| Additional Statistics | sqlite_stat4 | This option adds additional logic to the ANALYZE command and to the query planner that can help SQLite to chose a better query plan under certain situations. The ANALYZE command is enhanced to collect histogram data from all columns of every index and store that data in the sqlite_stat4 table.

The query planner will then use the histogram data to help it make better index choices. The downside of this compile-time option is that it violates the query planner stability guarantee making it more difficult to ensure consistent performance in mass-produced applications.

SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3. STAT3 only recorded histogram data for the left-most column of each index whereas the STAT4 enhancement records histogram data from all columns of each index.

The SQLITE_ENABLE_STAT3 compile-time option is a no-op and is ignored if the SQLITE_ENABLE_STAT4 compile-time option is used | +| Allow URI Authority | sqlite_allow_uri_authority | URI filenames normally throws an error if the authority section is not either empty or "localhost".

However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way | +| App Armor | sqlite_app_armor | When defined, this C-preprocessor macro activates extra code that attempts to detect misuse of the SQLite API, such as passing in NULL pointers to required parameters or using objects after they have been destroyed.

App Armor is not available under `Windows`. | +| Disable Load Extensions | sqlite_omit_load_extension | Loading of external extensions is enabled by default.

To disable extension loading add the build tag `sqlite_omit_load_extension`. | +| Foreign Keys | sqlite_foreign_keys | This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.

Each database connection can always turn enforcement of foreign key constraints on and off and run-time using the foreign_keys pragma.

Enforcement of foreign key constraints is normally off by default, but if this compile-time parameter is set to 1, enforcement of foreign key constraints will be on by default | +| Full Auto Vacuum | sqlite_vacuum_full | Set the default auto vacuum to full | +| Incremental Auto Vacuum | sqlite_vacuum_incr | Set the default auto vacuum to incremental | +| Full Text Search Engine | sqlite_fts5 | When this option is defined in the amalgamation, versions 5 of the full-text search engine (fts5) is added to the build automatically | +| International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build | +| Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements.
  • PRAGMA function_list
  • PRAGMA module_list
  • PRAGMA pragma_list
| +| JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically | +| Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.

When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.

The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.

On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information | +| Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | +| Tracing / Debug | sqlite_trace | Activate trace functions | +| User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. | + +# Compilation + +This package requires `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler. + +If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package. Then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. + +## Android + +This package can be compiled for android. +Compile with: + +```bash +go build --tags "android" +``` + +For more information see [#201](https://github.com/mattn/go-sqlite3/issues/201) + +# ARM + +To compile for `ARM` use the following environment. + +```bash +env CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \ + CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 \ + go build -v +``` + +Additional information: +- [#242](https://github.com/mattn/go-sqlite3/issues/242) +- [#504](https://github.com/mattn/go-sqlite3/issues/504) + +# Cross Compile + +This library can be cross-compiled. + +In some cases you are required to the `CC` environment variable with the cross compiler. + +Additional information: +- [#491](https://github.com/mattn/go-sqlite3/issues/491) +- [#560](https://github.com/mattn/go-sqlite3/issues/560) + +# Google Cloud Platform + +Building on GCP is not possible because `Google Cloud Platform does not allow `gcc` to be executed. + +Please work only with compiled final binaries. + +## Linux + +To compile this package on Linux you must install the development tools for your linux distribution. + +To compile under linux use the build tag `linux`. + +```bash +go build --tags "linux" +``` + +If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. + +``` +go build --tags "libsqlite3 linux" +``` + +### Alpine + +When building in an `alpine` container run the following command before building. + +``` +apk add --update gcc musl-dev +``` + +### Fedora + +```bash +sudo yum groupinstall "Development Tools" "Development Libraries" +``` + +### Ubuntu + +```bash +sudo apt-get install build-essential +``` + +## Mac OSX + +OSX should have all the tools present to compile this package, if not install XCode this will add all the developers tools. + +Required dependency + +```bash +brew install sqlite3 +``` + +For OSX there is an additional package install which is required if you whish to build the `icu` extension. + +This additional package can be installed with `homebrew`. + +```bash +brew upgrade icu4c +``` + +To compile for Mac OSX. + +```bash +go build --tags "darwin" +``` + +If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. + +``` +go build --tags "libsqlite3 darwin" +``` + +Additional information: +- [#206](https://github.com/mattn/go-sqlite3/issues/206) +- [#404](https://github.com/mattn/go-sqlite3/issues/404) + +## Windows + +To compile this package on Windows OS you must have the `gcc` compiler installed. + +1) Install a Windows `gcc` toolchain. +2) Add the `bin` folders to the Windows path if the installer did not do this by default. +3) Open a terminal for the TDM-GCC toolchain, can be found in the Windows Start menu. +4) Navigate to your project folder and run the `go build ...` command for this package. + +For example the TDM-GCC Toolchain can be found [here](ttps://sourceforge.net/projects/tdm-gcc/). + +## Errors + +- Compile error: `can not be used when making a shared object; recompile with -fPIC` + + When receiving a compile time error referencing recompile with `-FPIC` then you + are probably using a hardend system. + + You can copile the library on a hardend system with the following command. + + ```bash + go build -ldflags '-extldflags=-fno-PIC' + ``` + + More details see [#120](https://github.com/mattn/go-sqlite3/issues/120) + +- Can't build go-sqlite3 on windows 64bit. > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit. > See: [#27](https://github.com/mattn/go-sqlite3/issues/27) -* Getting insert error while query is opened. +- `go get github.com/mattn/go-sqlite3` throws compilation error. + + `gcc` throws: `internal compiler error` + + Remove the download repository from your disk and try re-install with: + + ```bash + go install github.com/mattn/go-sqlite3 + ``` + +# User Authentication + +This package supports the SQLite User Authentication module. + +## Compile + +To use the User authentication module the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features). + +## Usage + +### Create protected database + +To create a database protected by user authentication provide the following argument to the connection string `_auth`. +This will enable user authentication within the database. This option however requires two additional arguments: + +- `_auth_user` +- `_auth_pass` + +When `_auth` is present on the connection string user authentication will be enabled and the provided user will be created +as an `admin` user. After initial creation, the parameter `_auth` has no effect anymore and can be omitted from the connection string. + +Example connection string: + +Create an user authentication database with user `admin` and password `admin`. + +`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin` + +Create an user authentication database with user `admin` and password `admin` and use `SHA1` for the password encoding. + +`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1` + +### Password Encoding + +The passwords within the user authentication module of SQLite are encoded with the SQLite function `sqlite_cryp`. +This function uses a ceasar-cypher which is quite insecure. +This library provides several additional password encoders which can be configured through the connection string. + +The password cypher can be configured with the key `_auth_crypt`. And if the configured password encoder also requires an +salt this can be configured with `_auth_salt`. + +#### Available Encoders + +- SHA1 +- SSHA1 (Salted SHA1) +- SHA256 +- SSHA256 (salted SHA256) +- SHA384 +- SSHA384 (salted SHA384) +- SHA512 +- SSHA512 (salted SHA512) + +### Restrictions + +Operations on the database regarding to user management can only be preformed by an administrator user. + +### Support + +The user authentication supports two kinds of users + +- administrators +- regular users + +### User Management + +User management can be done by directly using the `*SQLiteConn` or by SQL. + +#### SQL + +The following sql functions are available for user management. + +| Function | Arguments | Description | +|----------|-----------|-------------| +| `authenticate` | username `string`, password `string` | Will authenticate an user, this is done by the connection; and should not be used manually. | +| `auth_user_add` | username `string`, password `string`, admin `int` | This function will add an user to the database.
if the database is not protected by user authentication it will enable it. Argument `admin` is an integer identifying if the added user should be an administrator. Only Administrators can add administrators. | +| `auth_user_change` | username `string`, password `string`, admin `int` | Function to modify an user. Users can change their own password, but only an administrator can change the administrator flag. | +| `authUserDelete` | username `string` | Delete an user from the database. Can only be used by an administrator. The current logged in administrator cannot be deleted. This is to make sure their is always an administrator remaining. | + +These functions will return an integer. + +- 0 (SQLITE_OK) +- 23 (SQLITE_AUTH) Failed to perform due to authentication or insufficient privileges + +##### Examples + +```sql +// Autheticate user +// Create Admin User +SELECT auth_user_add('admin2', 'admin2', 1); + +// Change password for user +SELECT auth_user_change('user', 'userpassword', 0); + +// Delete user +SELECT user_delete('user'); +``` + +#### *SQLiteConn + +The following functions are available for User authentication from the `*SQLiteConn`. + +| Function | Description | +|----------|-------------| +| `Authenticate(username, password string) error` | Authenticate user | +| `AuthUserAdd(username, password string, admin bool) error` | Add user | +| `AuthUserChange(username, password string, admin bool) error` | Modify user | +| `AuthUserDelete(username string) error` | Delete user | + +### Attached database + +When using attached databases. SQLite will use the authentication from the `main` database for the attached database(s). + +# Extensions + +If you want your own extension to be listed here or you want to add a reference to an extension; please submit an Issue for this. + +## Spatialite + +Spatialite is available as an extension to SQLite, and can be used in combination with this repository. +For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatialite). + +# FAQ + +- Getting insert error while query is opened. > You can pass some arguments into the connection string, for example, a URI. > See: [#39](https://github.com/mattn/go-sqlite3/issues/39) -* Do you want to cross compile? mingw on Linux or Mac? +- Do you want to cross compile? mingw on Linux or Mac? > See: [#106](https://github.com/mattn/go-sqlite3/issues/106) > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html -* Want to get time.Time with current locale +- Want to get time.Time with current locale Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`. -* Can I use this in multiple routines concurrently? +- Can I use this in multiple routines concurrently? - Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209). + Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209), [#274](https://github.com/mattn/go-sqlite3/issues/274). -* Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database? +- Why I'm getting `no such table` error? + + Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database? Each connection to :memory: opens a brand new in-memory sql database, so if the stdlib's sql engine happens to open another connection and you've only specified ":memory:", that connection will see a brand new database. A workaround is to use "file::memory:?mode=memory&cache=shared". Every - connection to this string will point to the same in-memory database. See - [#204](https://github.com/mattn/go-sqlite3/issues/204) for more info. + connection to this string will point to the same in-memory database. + + For more information see + * [#204](https://github.com/mattn/go-sqlite3/issues/204) + * [#511](https://github.com/mattn/go-sqlite3/issues/511) -License -------- +- Reading from database with large amount of goroutines fails on OSX. -MIT: http://mattn.mit-license.org/2012 + OS X limits OS-wide to not have more than 1000 files open simultaneously by default. + + For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289) + +- Trying to execure a `.` (dot) command throws an error. + + Error: `Error: near ".": syntax error` + Dot command are part of SQLite3 CLI not of this library. + + You need to implement the feature or call the sqlite3 cli. + + More infomation see [#305](https://github.com/mattn/go-sqlite3/issues/305) + +- Error: `database is locked` + + When you get an database is locked. Please use the following options. + + Add to DSN: `cache=shared` + + Example: + ```go + db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared") + ``` + + Second please set the database connections of the SQL package to 1. + + ```go + db.SetMaxOpenConn(1) + ``` + + More information see [#209](https://github.com/mattn/go-sqlite3/issues/209) + +# License + +MIT: http://mattn.mit-license.org/2018 sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h @@ -91,7 +511,8 @@ The -binding suffix was added to avoid build failures under gccgo. In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3. -Author ------- +# Author Yasuhiro Matsumoto (a.k.a mattn) + +G.J.R. Timmer diff --git a/vendor/github.com/mattn/go-sqlite3/_example/trace/main.go b/vendor/github.com/mattn/go-sqlite3/_example/trace/main.go index 9f83ee1..bef3d15 100644 --- a/vendor/github.com/mattn/go-sqlite3/_example/trace/main.go +++ b/vendor/github.com/mattn/go-sqlite3/_example/trace/main.go @@ -95,7 +95,7 @@ func main() { ConnectHook: func(conn *sqlite3.SQLiteConn) error { err := conn.SetTrace(&sqlite3.TraceConfig{ Callback: traceCallback, - EventMask: uint(eventMask), + EventMask: eventMask, WantExpandedSQL: true, }) return err diff --git a/vendor/github.com/mattn/go-sqlite3/callback.go b/vendor/github.com/mattn/go-sqlite3/callback.go index 29ece3d..5a735c0 100644 --- a/vendor/github.com/mattn/go-sqlite3/callback.go +++ b/vendor/github.com/mattn/go-sqlite3/callback.go @@ -331,8 +331,18 @@ func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error { return nil } +func callbackRetNil(ctx *C.sqlite3_context, v reflect.Value) error { + return nil +} + func callbackRet(typ reflect.Type) (callbackRetConverter, error) { switch typ.Kind() { + case reflect.Interface: + errorInterface := reflect.TypeOf((*error)(nil)).Elem() + if typ.Implements(errorInterface) { + return callbackRetNil, nil + } + fallthrough case reflect.Slice: if typ.Elem().Kind() != reflect.Uint8 { return nil, errors.New("the only supported slice type is []byte") diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c index b67d0a5..f077152 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c @@ -1,7 +1,7 @@ #ifndef USE_LIBSQLITE3 /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.21.0. By combining all the individual C code files into this +** version 3.24.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -214,7 +214,7 @@ static const char * const sqlite3azCompileOpt[] = { "ENABLE_BATCH_ATOMIC_WRITE", #endif #if SQLITE_ENABLE_CEROD - "ENABLE_CEROD", + "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), #endif #if SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", @@ -312,6 +312,9 @@ static const char * const sqlite3azCompileOpt[] = { #if SQLITE_ENABLE_SNAPSHOT "ENABLE_SNAPSHOT", #endif +#if SQLITE_ENABLE_SORTER_REFERENCES + "ENABLE_SORTER_REFERENCES", +#endif #if SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif @@ -1148,9 +1151,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.21.0" -#define SQLITE_VERSION_NUMBER 3021000 -#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827" +#define SQLITE_VERSION "3.24.0" +#define SQLITE_VERSION_NUMBER 3024000 +#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1495,6 +1498,8 @@ SQLITE_API int sqlite3_exec( ** the most recent error can be obtained using ** [sqlite3_extended_errcode()]. */ +#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) +#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) @@ -1527,6 +1532,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) @@ -1534,10 +1540,13 @@ SQLITE_API int sqlite3_exec( #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) +#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) +#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) @@ -2085,6 +2094,12 @@ struct sqlite3_io_methods { ** so that all subsequent write operations are independent. ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain +** a file lock using the xLock or xShmLock methods of the VFS to wait +** for up to M milliseconds before failing, where M is the single +** unsigned integer parameter. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -2119,6 +2134,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -2156,12 +2172,18 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. ** -** The value of the iVersion field is initially 1 but may be larger in -** future versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. Note that the structure -** of the sqlite3_vfs object changes in the transaction between -** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not -** modified. +** The VFS interface is sometimes extended by adding new methods onto +** the end. Each time such an extension occurs, the iVersion field +** is incremented. The iVersion value started out as 1 in +** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 +** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased +** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields +** may be appended to the sqlite3_vfs object and the iVersion value +** may increase again in future versions of SQLite. +** Note that the structure +** of the sqlite3_vfs object changes in the transition from +** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] +** and yet the iVersion field was not modified. ** ** The szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of @@ -2938,6 +2960,22 @@ struct sqlite3_mem_methods { ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. +** +** [[SQLITE_CONFIG_SORTERREF_SIZE]] +**
    SQLITE_CONFIG_SORTERREF_SIZE +**
    The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter +** of type (int) - the new value of the sorter-reference size threshold. +** Usually, when SQLite uses an external sort to order records according +** to an ORDER BY clause, all fields required by the caller are present in the +** sorted records. However, if SQLite determines based on the declared type +** of a table column that its values are likely to be very large - larger +** than the configured sorter-reference size threshold - then a reference +** is stored in each sorted record and the required column values loaded +** from the database as records are returned in sorted order. The default +** value for this option is to never use this optimization. Specifying a +** negative value for this option restores the default behaviour. +** This option is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2967,6 +3005,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ +#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ /* ** CAPI3REF: Database Connection Configuration Options @@ -3069,8 +3108,9 @@ struct sqlite3_mem_methods { ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to ** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer +** is an integer - positive to disable checkpoints-on-close, or zero (the +** default) to enable them, and negative to leave the setting unchanged. +** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. **
    @@ -3084,8 +3124,39 @@ struct sqlite3_mem_methods { ** slower. But the QPSG has the advantage of more predictable behavior. With ** the QPSG active, SQLite will always use the same query plan in the field as ** was used during testing in the lab. +** The first argument to this setting is an integer which is 0 to disable +** the QPSG, positive to enable QPSG, or negative to leave the setting +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether the QPSG is disabled or enabled +** following this call. ** ** +**
    SQLITE_DBCONFIG_TRIGGER_EQP
    +**
    By default, the output of EXPLAIN QUERY PLAN commands does not +** include output for any operations performed by trigger programs. This +** option is used to set or clear (the default) a flag that governs this +** behavior. The first parameter passed to this operation is an integer - +** positive to enable output for trigger programs, or zero to disable it, +** or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which is written +** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if +** it is not disabled, 1 if it is. +**
    +** +**
    SQLITE_DBCONFIG_RESET_DATABASE
    +**
    Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run +** [VACUUM] in order to reset a database back to an empty database +** with no schema and no content. The following process works even for +** a badly corrupted database file: +**
      +**
    1. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); +**
    2. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); +**
    3. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); +**
    +** Because resetting a database is destructive and irreversible, the +** process requires the use of this obscure API and multiple steps to help +** ensure that it does not happen by accident. +**
    ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -3096,7 +3167,9 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ - +#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ +#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -3502,16 +3575,16 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. -** These routines understand most of the common K&R formatting options, -** plus some additional non-standard formats, detailed below. -** Note that some of the more obscure formatting options from recent -** C-library standards are omitted from this implementation. +** These routines understand most of the common formatting options from +** the standard library printf() +** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). +** See the [built-in printf()] documentation for details. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. +** results into memory obtained from [sqlite3_malloc64()]. ** The strings returned by these two routines should be ** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough ** memory to hold the resulting string. ** ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from @@ -3535,71 +3608,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). ** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", "%w" and "%z" options. -** -** ^(The %q option works like %s in that it substitutes a nul-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal.)^ By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, assume the string variable zText contains text as follows: -** -**
    -**  char *zText = "It's a happy day!";
    -** 
    -** -** One can use this text in an SQL statement as follows: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
    -**  INSERT INTO table1 VALUES('It''s a happy day!')
    -** 
    -** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
    -**  INSERT INTO table1 VALUES('It's a happy day!');
    -** 
    -** -** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. -** -** ^(The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Additionally, if the parameter in the -** argument list is a NULL pointer, %Q substitutes the text "NULL" (without -** single quotes).)^ So, for example, one could say: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** ^(The "%w" formatting option is like "%q" except that it expects to -** be contained within double-quotes instead of single quotes, and it -** escapes the double-quote character instead of the single-quote -** character.)^ The "%w" formatting option is intended for safely inserting -** table and column names into a constructed SQL statement. -** -** ^(The "%z" formatting option works like "%s" but with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string.)^ +** See also: [built-in printf()], [printf() SQL function] */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); @@ -3957,8 +3966,8 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** KEYWORDS: SQLITE_TRACE ** ** These constants identify classes of events that can be monitored -** using the [sqlite3_trace_v2()] tracing logic. The third argument -** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of +** using the [sqlite3_trace_v2()] tracing logic. The M argument +** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of ** the following constants. ^The first argument to the trace callback ** is one of the following constants. ** @@ -4665,13 +4674,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. **
  • +** ** **

    ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ** the extra prepFlags parameter, which is a bit array consisting of zero or ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The ** sqlite3_prepare_v2() interface works exactly the same as ** sqlite3_prepare_v3() with a zero prepFlags parameter. -** */ SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ @@ -5804,6 +5813,9 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** datatype of the value ** sqlite3_value_numeric_type   ** →  Best numeric datatype of the value +** sqlite3_value_nochange   +** →  True if the column is unchanged in an UPDATE +** against a virtual table. ** ** ** Details: @@ -5852,6 +5864,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** +** ^Within the [xUpdate] method of a [virtual table], the +** sqlite3_value_nochange(X) interface returns true if and only if +** the column corresponding to X is unchanged by the UPDATE operation +** that the xUpdate method call was invoked to implement and if +** and the prior [xColumn] method call that was invoked to extracted +** the value for that column returned without setting a result (probably +** because it queried [sqlite3_vtab_nochange()] and found that the column +** was unchanging). ^Within an [xUpdate] method, any value for which +** sqlite3_value_nochange(X) is true will in all other respects appear +** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other +** than within an [xUpdate] method call for an UPDATE statement, then +** the return value is arbitrary and meaningless. +** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to @@ -5874,6 +5899,7 @@ SQLITE_API int sqlite3_value_bytes(sqlite3_value*); SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API int sqlite3_value_nochange(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -6529,6 +6555,41 @@ SQLITE_API char *sqlite3_temp_directory; */ SQLITE_API char *sqlite3_data_directory; +/* +** CAPI3REF: Win32 Specific Interface +** +** These interfaces are available only on Windows. The +** [sqlite3_win32_set_directory] interface is used to set the value associated +** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to +** zValue, depending on the value of the type parameter. The zValue parameter +** should be NULL to cause the previous value to be freed via [sqlite3_free]; +** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] +** prior to being used. The [sqlite3_win32_set_directory] interface returns +** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, +** or [SQLITE_NOMEM] if memory could not be allocated. The value of the +** [sqlite3_data_directory] variable is intended to act as a replacement for +** the current directory on the sub-platforms of Win32 where that concept is +** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and +** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the +** sqlite3_win32_set_directory interface except the string parameter must be +** UTF-8 or UTF-16, respectively. +*/ +SQLITE_API int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +); +SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); +SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); + +/* +** CAPI3REF: Win32 Directory Types +** +** These macros are only available on Windows. They define the allowed values +** for the type argument to the [sqlite3_win32_set_directory] interface. +*/ +#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 +#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 + /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} @@ -7261,6 +7322,10 @@ struct sqlite3_index_info { /* ** CAPI3REF: Virtual Table Scan Flags +** +** Virtual table implementations are allowed to set the +** [sqlite3_index_info].idxFlags field to some combination of +** these bits. */ #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ @@ -7976,9 +8041,9 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** -** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes ** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] ** case is a short-circuit path which does not actually invoke the ** underlying sqlite3_io_methods.xFileControl method. ** @@ -7990,7 +8055,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** -** See also: [SQLITE_FCNTL_LOCKSTATE] +** See also: [file control opcodes] */ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); @@ -8036,7 +8101,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ @@ -8047,7 +8112,191 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 +#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 +#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + +/* +** CAPI3REF: SQL Keyword Checking +** +** These routines provide access to the set of SQL language keywords +** recognized by SQLite. Applications can uses these routines to determine +** whether or not a specific identifier needs to be escaped (for example, +** by enclosing in double-quotes) so as not to confuse the parser. +** +** The sqlite3_keyword_count() interface returns the number of distinct +** keywords understood by SQLite. +** +** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** makes *Z point to that keyword expressed as UTF8 and writes the number +** of bytes in the keyword into *L. The string that *Z points to is not +** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns +** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z +** or L are NULL or invalid pointers then calls to +** sqlite3_keyword_name(N,Z,L) result in undefined behavior. +** +** The sqlite3_keyword_check(Z,L) interface checks to see whether or not +** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero +** if it is and zero if not. +** +** The parser used by SQLite is forgiving. It is often possible to use +** a keyword as an identifier as long as such use does not result in a +** parsing ambiguity. For example, the statement +** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and +** creates a new table named "BEGIN" with three columns named +** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid +** using keywords as identifiers. Common techniques used to avoid keyword +** name collisions include: +**

      +**
    • Put all identifier names inside double-quotes. This is the official +** SQL way to escape identifier names. +**
    • Put identifier names inside [...]. This is not standard SQL, +** but it is what SQL Server does and so lots of programmers use this +** technique. +**
    • Begin every identifier with the letter "Z" as no SQL keywords start +** with "Z". +**
    • Include a digit somewhere in every identifier name. +**
    +** +** Note that the number of keywords understood by SQLite can depend on +** compile-time options. For example, "VACUUM" is not a keyword if +** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, +** new keywords may be added to future releases of SQLite. +*/ +SQLITE_API int sqlite3_keyword_count(void); +SQLITE_API int sqlite3_keyword_name(int,const char**,int*); +SQLITE_API int sqlite3_keyword_check(const char*,int); + +/* +** CAPI3REF: Dynamic String Object +** KEYWORDS: {dynamic string} +** +** An instance of the sqlite3_str object contains a dynamically-sized +** string under construction. +** +** The lifecycle of an sqlite3_str object is as follows: +**
      +**
    1. ^The sqlite3_str object is created using [sqlite3_str_new()]. +**
    2. ^Text is appended to the sqlite3_str object using various +** methods, such as [sqlite3_str_appendf()]. +**
    3. ^The sqlite3_str object is destroyed and the string it created +** is returned using the [sqlite3_str_finish()] interface. +**
    +*/ +typedef struct sqlite3_str sqlite3_str; + +/* +** CAPI3REF: Create A New Dynamic String Object +** CONSTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_new(D)] interface allocates and initializes +** a new [sqlite3_str] object. To avoid memory leaks, the object returned by +** [sqlite3_str_new()] must be freed by a subsequent call to +** [sqlite3_str_finish(X)]. +** +** ^The [sqlite3_str_new(D)] interface always returns a pointer to a +** valid [sqlite3_str] object, though in the event of an out-of-memory +** error the returned object might be a special singleton that will +** silently reject new text, always return SQLITE_NOMEM from +** [sqlite3_str_errcode()], always return 0 for +** [sqlite3_str_length()], and always return NULL from +** [sqlite3_str_finish(X)]. It is always safe to use the value +** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter +** to any of the other [sqlite3_str] methods. +** +** The D parameter to [sqlite3_str_new(D)] may be NULL. If the +** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum +** length of the string contained in the [sqlite3_str] object will be +** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead +** of [SQLITE_MAX_LENGTH]. +*/ +SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); + +/* +** CAPI3REF: Finalize A Dynamic String +** DESTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X +** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] +** that contains the constructed string. The calling application should +** pass the returned value to [sqlite3_free()] to avoid a memory leak. +** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any +** errors were encountered during construction of the string. ^The +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the +** string in [sqlite3_str] object X is zero bytes long. +*/ +SQLITE_API char *sqlite3_str_finish(sqlite3_str*); + +/* +** CAPI3REF: Add Content To A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. +** +** ^The [sqlite3_str_appendf(X,F,...)] and +** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] +** functionality of SQLite to append formatted text onto the end of +** [sqlite3_str] object X. +** +** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S +** onto the end of the [sqlite3_str] object X. N must be non-negative. +** S must contain at least N non-zero bytes of content. To append a +** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] +** method instead. +** +** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of +** zero-terminated string S onto the end of [sqlite3_str] object X. +** +** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the +** single-byte character C onto the end of [sqlite3_str] object X. +** ^This method can be used, for example, to add whitespace indentation. +** +** ^The [sqlite3_str_reset(X)] method resets the string under construction +** inside [sqlite3_str] object X back to zero bytes in length. +** +** These methods do not return a result code. ^If an error occurs, that fact +** is recorded in the [sqlite3_str] object and can be recovered by a +** subsequent call to [sqlite3_str_errcode(X)]. +*/ +SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); +SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); +SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); +SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); +SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); +SQLITE_API void sqlite3_str_reset(sqlite3_str*); + +/* +** CAPI3REF: Status Of A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces return the current status of an [sqlite3_str] object. +** +** ^If any prior errors have occurred while constructing the dynamic string +** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return +** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns +** [SQLITE_NOMEM] following any out-of-memory error, or +** [SQLITE_TOOBIG] if the size of the dynamic string exceeds +** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. +** +** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, +** of the dynamic string under construction in [sqlite3_str] object X. +** ^The length returned by [sqlite3_str_length(X)] does not include the +** zero-termination byte. +** +** ^The [sqlite3_str_value(X)] method returns a pointer to the current +** content of the dynamic string under construction in X. The value +** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X +** and might be freed or altered by any subsequent method on the same +** [sqlite3_str] object. Applications must not used the pointer returned +** [sqlite3_str_value(X)] after any subsequent method call on the same +** object. ^Applications may change the content of the string returned +** by [sqlite3_str_value(X)] as long as they do not write into any bytes +** outside the range of 0 to [sqlite3_str_length(X)] and do not read or +** write any byte after any subsequent sqlite3_str method call. +*/ +SQLITE_API int sqlite3_str_errcode(sqlite3_str*); +SQLITE_API int sqlite3_str_length(sqlite3_str*); +SQLITE_API char *sqlite3_str_value(sqlite3_str*); /* ** CAPI3REF: SQLite Runtime Status @@ -8282,6 +8531,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** ** +** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
    SQLITE_DBSTATUS_CACHE_SPILL
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk in the middle of a transaction due to the page +** cache overflowing. Transactions are more efficient if they are written +** to disk all at once. When pages spill mid-transaction, that introduces +** additional overhead. This parameter can be used help identify +** inefficiencies that can be resolve by increasing the cache size. +**
    +** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    **
    This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been @@ -8301,7 +8559,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_SPILL 12 +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -9301,6 +9560,40 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); */ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); +/* +** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE +** +** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] +** method of a [virtual table], then it returns true if and only if the +** column is being fetched as part of an UPDATE operation during which the +** column value will not change. Applications might use this to substitute +** a return value that is less expensive to compute and that the corresponding +** [xUpdate] method understands as a "no-change" value. +** +** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that +** the column is not changed by the UPDATE statement, then the xColumn +** method can optionally return without setting a result, without calling +** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. +** In that case, [sqlite3_value_nochange(X)] will return true for the +** same column in the [xUpdate] method. +*/ +SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); + +/* +** CAPI3REF: Determine The Collation For a Virtual Table Constraint +** +** This function may only be called from within a call to the [xBestIndex] +** method of a [virtual table]. +** +** The first argument must be the sqlite3_index_info object that is the +** first parameter to the xBestIndex() method. The second argument must be +** an index into the aConstraint[] array belonging to the sqlite3_index_info +** structure passed to xBestIndex. This function returns a pointer to a buffer +** containing the name of the collation sequence for the corresponding +** constraint. +*/ +SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); + /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} @@ -9747,6 +10040,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Serialize a database +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contiguous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Deserialize a database +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnect from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is resposible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database using calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -9894,16 +10309,23 @@ extern "C" { /* ** CAPI3REF: Session Object Handle +** +** An instance of this object is a [session] that can be used to +** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle +** +** An instance of this object acts as a cursor for iterating +** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object +** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is @@ -9940,6 +10362,7 @@ SQLITE_API int sqlite3session_create( /* ** CAPI3REF: Delete A Session Object +** DESTRUCTOR: sqlite3_session ** ** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the @@ -9955,6 +10378,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object +** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When @@ -9974,6 +10398,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag +** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: @@ -10003,6 +10428,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) /* ** CAPI3REF: Attach A Table To A Session Object +** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach ** to the session object passed as the first argument. All subsequent changes @@ -10028,6 +10454,35 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) ** ** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. +** +**

    Special sqlite_stat1 Handling

    +** +** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to +** some of the rules above. In SQLite, the schema of sqlite_stat1 is: +**
    +**        CREATE TABLE sqlite_stat1(tbl,idx,stat)  
    +**  
    +** +** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are +** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes +** are recorded for rows for which (idx IS NULL) is true. However, for such +** rows a zero-length blob (SQL value X'') is stored in the changeset or +** patchset instead of a NULL value. This allows such changesets to be +** manipulated by legacy implementations of sqlite3changeset_invert(), +** concat() and similar. +** +** The sqlite3changeset_apply() function automatically converts the +** zero-length blob back to a NULL value when updating the sqlite_stat1 +** table. However, if the application calls sqlite3changeset_new(), +** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset +** iterator directly (including on a changeset iterator passed to a +** conflict-handler callback) then the X'' value is returned. The application +** must translate X'' to NULL itself if required. +** +** Legacy (older than 3.22.0) versions of the sessions module cannot capture +** changes made to the sqlite_stat1 table. Legacy versions of the +** sqlite3changeset_apply() function silently ignore any modifications to the +** sqlite_stat1 table that are part of a changeset or patchset. */ SQLITE_API int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ @@ -10036,6 +10491,7 @@ SQLITE_API int sqlite3session_attach( /* ** CAPI3REF: Set a table filter on a Session Object. +** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called @@ -10054,6 +10510,7 @@ SQLITE_API void sqlite3session_table_filter( /* ** CAPI3REF: Generate A Changeset From A Session Object +** METHOD: sqlite3_session ** ** Obtain a changeset containing changes to the tables attached to the ** session object passed as the first argument. If successful, @@ -10163,7 +10620,8 @@ SQLITE_API int sqlite3session_changeset( ); /* -** CAPI3REF: Load The Difference Between Tables Into A Session +** CAPI3REF: Load The Difference Between Tables Into A Session +** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the @@ -10228,6 +10686,7 @@ SQLITE_API int sqlite3session_diff( /* ** CAPI3REF: Generate A Patchset From A Session Object +** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** @@ -10279,6 +10738,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset +** CONSTRUCTOR: sqlite3_changeset_iter ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK @@ -10319,6 +10779,7 @@ SQLITE_API int sqlite3changeset_start( /* ** CAPI3REF: Advance A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to @@ -10343,6 +10804,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10377,6 +10839,7 @@ SQLITE_API int sqlite3changeset_op( /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table +** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** @@ -10408,6 +10871,7 @@ SQLITE_API int sqlite3changeset_pk( /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10438,6 +10902,7 @@ SQLITE_API int sqlite3changeset_old( /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10471,6 +10936,7 @@ SQLITE_API int sqlite3changeset_new( /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either @@ -10498,6 +10964,7 @@ SQLITE_API int sqlite3changeset_conflict( /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case @@ -10514,6 +10981,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( /* ** CAPI3REF: Finalize A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. @@ -10530,6 +10998,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** +**
     **   sqlite3changeset_start();
     **   while( SQLITE_ROW==sqlite3changeset_next() ){
     **     // Do something with change.
    @@ -10538,6 +11007,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
     **   if( rc!=SQLITE_OK ){
     **     // An error has occurred 
     **   }
    +** 
    */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); @@ -10585,6 +11055,7 @@ SQLITE_API int sqlite3changeset_invert( ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** +**
     **   sqlite3_changegroup *pGrp;
     **   rc = sqlite3_changegroup_new(&pGrp);
     **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
    @@ -10595,6 +11066,7 @@ SQLITE_API int sqlite3changeset_invert(
     **     *ppOut = 0;
     **     *pnOut = 0;
     **   }
    +** 
    ** ** Refer to the sqlite3_changegroup documentation below for details. */ @@ -10610,11 +11082,15 @@ SQLITE_API int sqlite3changeset_concat( /* ** CAPI3REF: Changegroup Handle +** +** A changegroup is an object used to combine two or more +** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object +** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -10652,6 +11128,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); /* ** CAPI3REF: Add A Changeset To A Changegroup +** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. @@ -10729,6 +11206,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup @@ -10759,25 +11237,25 @@ SQLITE_API int sqlite3changegroup_output( /* ** CAPI3REF: Delete A Changegroup Object +** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset to a database. This function attempts to update the -** "main" database attached to handle db with the changes found in the -** changeset passed via the second and third arguments. +** Apply a changeset or patchset to a database. These functions attempt to +** update the "main" database attached to handle db with the changes found in +** the changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to this function is the "filter +** The fourth argument (xFilter) passed to these functions is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument to this function as the first. If the "filter -** callback" returns zero, then no attempt is made to apply any changes to -** the table. Otherwise, if the return value is non-zero or the xFilter -** argument to this function is NULL, all changes related to the table are -** attempted. +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -10822,7 +11300,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** **
    **
    DELETE Changes
    -** For each DELETE change, this function checks if the target database +** For each DELETE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all non-primary key columns also match the values stored in @@ -10867,7 +11345,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** [SQLITE_CHANGESET_REPLACE]. ** **
    UPDATE Changes
    -** For each UPDATE change, this function checks if the target database +** For each UPDATE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all modified non-primary key columns also match the values @@ -10898,11 +11376,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by this function are enclosed in a savepoint transaction. +** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. +** +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +** may set (*ppRebase) to point to a "rebase" that may be used with the +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +** is set to the size of the buffer in bytes. It is the responsibility of the +** caller to eventually free any such buffer using sqlite3_free(). The buffer +** is only allocated and populated if one or more conflicts were encountered +** while applying the patchset. See comments surrounding the sqlite3_rebaser +** APIs for further details. +** +** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. +** +** Note that the sqlite3changeset_apply_v2() API is still experimental +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -10919,6 +11414,41 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* Combination of SESSION_APPLY_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +** +** The following flags may passed via the 9th parameter to +** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: +** +**
    +**
    SQLITE_CHANGESETAPPLY_NOSAVEPOINT
    +** Usually, the sessions module encloses all operations performed by +** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The +** SAVEPOINT is committed if the changeset or patchset is successfully +** applied, or rolled back if an error occurs. Specifying this flag +** causes the sessions module to omit this savepoint. In this case, if the +** caller has an open transaction or savepoint when apply_v2() is called, +** it may revert the partially applied changeset by rolling it back. +*/ +#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -11016,6 +11546,161 @@ SQLITE_API int sqlite3changeset_apply( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** CAPI3REF: Rebasing changesets +** EXPERIMENTAL +** +** Suppose there is a site hosting a database in state S0. And that +** modifications are made that move that database to state S1 and a +** changeset recorded (the "local" changeset). Then, a changeset based +** on S0 is received from another site (the "remote" changeset) and +** applied to the database. The database is then in state +** (S1+"remote"), where the exact state depends on any conflict +** resolution decisions (OMIT or REPLACE) made while applying "remote". +** Rebasing a changeset is to update it to take those conflict +** resolution decisions into account, so that the same conflicts +** do not have to be resolved elsewhere in the network. +** +** For example, if both the local and remote changesets contain an +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": +** +** local: INSERT INTO t1 VALUES(1, 'v1'); +** remote: INSERT INTO t1 VALUES(1, 'v2'); +** +** and the conflict resolution is REPLACE, then the INSERT change is +** removed from the local changeset (it was overridden). Or, if the +** conflict resolution was "OMIT", then the local changeset is modified +** to instead contain: +** +** UPDATE t1 SET b = 'v2' WHERE a=1; +** +** Changes within the local changeset are rebased as follows: +** +**
    +**
    Local INSERT
    +** This may only conflict with a remote INSERT. If the conflict +** resolution was OMIT, then add an UPDATE change to the rebased +** changeset. Or, if the conflict resolution was REPLACE, add +** nothing to the rebased changeset. +** +**
    Local DELETE
    +** This may conflict with a remote UPDATE or DELETE. In both cases the +** only possible resolution is OMIT. If the remote operation was a +** DELETE, then add no change to the rebased changeset. If the remote +** operation was an UPDATE, then the old.* fields of change are updated +** to reflect the new.* values in the UPDATE. +** +**
    Local UPDATE
    +** This may conflict with a remote UPDATE or DELETE. If it conflicts +** with a DELETE, and the conflict resolution was OMIT, then the update +** is changed into an INSERT. Any undefined values in the new.* record +** from the update change are filled in using the old.* values from +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, +** the UPDATE change is simply omitted from the rebased changeset. +** +** If conflict is with a remote UPDATE and the resolution is OMIT, then +** the old.* values are rebased using the new.* values in the remote +** change. Or, if the resolution is REPLACE, then the change is copied +** into the rebased changeset with updates to columns also updated by +** the conflicting remote UPDATE removed. If this means no columns would +** be updated, the change is omitted. +**
    +** +** A local change may be rebased against multiple remote changes +** simultaneously. If a single key is modified by multiple remote +** changesets, they are combined as follows before the local changeset +** is rebased: +** +**
      +**
    • If there has been one or more REPLACE resolutions on a +** key, it is rebased according to a REPLACE. +** +**
    • If there have been no REPLACE resolutions on a key, then +** the local changeset is rebased according to the most recent +** of the OMIT resolutions. +**
    +** +** Note that conflict resolutions from multiple remote changesets are +** combined on a per-field basis, not per-row. This means that in the +** case of multiple remote UPDATE operations, some fields of a single +** local change may be rebased for REPLACE while others are rebased for +** OMIT. +** +** In order to rebase a local changeset, the remote changeset must first +** be applied to the local database using sqlite3changeset_apply_v2() and +** the buffer of rebase information captured. Then: +** +**
      +**
    1. An sqlite3_rebaser object is created by calling +** sqlite3rebaser_create(). +**
    2. The new object is configured with the rebase buffer obtained from +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). +** If the local changeset is to be rebased against multiple remote +** changesets, then sqlite3rebaser_configure() should be called +** multiple times, in the same order that the multiple +** sqlite3changeset_apply_v2() calls were made. +**
    3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). +**
    4. The sqlite3_rebaser object is deleted by calling +** sqlite3rebaser_delete(). +**
    +*/ +typedef struct sqlite3_rebaser sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object. +** EXPERIMENTAL +** +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to +** point to the new object and return SQLITE_OK. Otherwise, if an error +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) +** to NULL. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object. +** EXPERIMENTAL +** +** Configure the changeset rebaser object to rebase changesets according +** to the conflict resolutions described by buffer pRebase (size nRebase +** bytes), which must have been obtained from a previous call to +** sqlite3changeset_apply_v2(). +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, const void *pRebase +); + +/* +** CAPI3REF: Rebase a changeset +** EXPERIMENTAL +** +** Argument pIn must point to a buffer containing a changeset nIn bytes +** in size. This function allocates and populates a buffer with a copy +** of the changeset rebased rebased according to the configuration of the +** rebaser object passed as the first argument. If successful, (*ppOut) +** is set to point to the new buffer containing the rebased changset and +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the +** responsibility of the caller to eventually free the new buffer using +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) +** are set to zero and an SQLite error code returned. +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object. +** EXPERIMENTAL +** +** Delete the changeset rebaser object and all associated resources. There +** should be one call to this function for each successful invocation +** of sqlite3rebaser_create(). +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); + /* ** CAPI3REF: Streaming Versions of API functions. ** @@ -11025,6 +11710,7 @@ SQLITE_API int sqlite3changeset_apply( ** ** **
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_strm[sqlite3changeset_apply] +**
    sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] **
    sqlite3changeset_concat_strm[sqlite3changeset_concat] **
    sqlite3changeset_invert_strm[sqlite3changeset_invert] **
    sqlite3changeset_start_strm[sqlite3changeset_start] @@ -11120,6 +11806,23 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, @@ -11157,6 +11860,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); /* @@ -12492,105 +13202,109 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_ESCAPE 58 #define TK_ID 59 #define TK_COLUMNKW 60 -#define TK_FOR 61 -#define TK_IGNORE 62 -#define TK_INITIALLY 63 -#define TK_INSTEAD 64 -#define TK_NO 65 -#define TK_KEY 66 -#define TK_OF 67 -#define TK_OFFSET 68 -#define TK_PRAGMA 69 -#define TK_RAISE 70 -#define TK_RECURSIVE 71 -#define TK_REPLACE 72 -#define TK_RESTRICT 73 -#define TK_ROW 74 -#define TK_TRIGGER 75 -#define TK_VACUUM 76 -#define TK_VIEW 77 -#define TK_VIRTUAL 78 -#define TK_WITH 79 -#define TK_REINDEX 80 -#define TK_RENAME 81 -#define TK_CTIME_KW 82 -#define TK_ANY 83 -#define TK_BITAND 84 -#define TK_BITOR 85 -#define TK_LSHIFT 86 -#define TK_RSHIFT 87 -#define TK_PLUS 88 -#define TK_MINUS 89 -#define TK_STAR 90 -#define TK_SLASH 91 -#define TK_REM 92 -#define TK_CONCAT 93 -#define TK_COLLATE 94 -#define TK_BITNOT 95 -#define TK_INDEXED 96 -#define TK_STRING 97 -#define TK_JOIN_KW 98 -#define TK_CONSTRAINT 99 -#define TK_DEFAULT 100 -#define TK_NULL 101 -#define TK_PRIMARY 102 -#define TK_UNIQUE 103 -#define TK_CHECK 104 -#define TK_REFERENCES 105 -#define TK_AUTOINCR 106 -#define TK_ON 107 -#define TK_INSERT 108 -#define TK_DELETE 109 -#define TK_UPDATE 110 -#define TK_SET 111 -#define TK_DEFERRABLE 112 -#define TK_FOREIGN 113 -#define TK_DROP 114 -#define TK_UNION 115 -#define TK_ALL 116 -#define TK_EXCEPT 117 -#define TK_INTERSECT 118 -#define TK_SELECT 119 -#define TK_VALUES 120 -#define TK_DISTINCT 121 -#define TK_DOT 122 -#define TK_FROM 123 -#define TK_JOIN 124 -#define TK_USING 125 -#define TK_ORDER 126 -#define TK_GROUP 127 -#define TK_HAVING 128 -#define TK_LIMIT 129 -#define TK_WHERE 130 -#define TK_INTO 131 -#define TK_FLOAT 132 -#define TK_BLOB 133 -#define TK_INTEGER 134 -#define TK_VARIABLE 135 -#define TK_CASE 136 -#define TK_WHEN 137 -#define TK_THEN 138 -#define TK_ELSE 139 -#define TK_INDEX 140 -#define TK_ALTER 141 -#define TK_ADD 142 -#define TK_ISNOT 143 -#define TK_FUNCTION 144 -#define TK_COLUMN 145 -#define TK_AGG_FUNCTION 146 -#define TK_AGG_COLUMN 147 -#define TK_UMINUS 148 -#define TK_UPLUS 149 -#define TK_REGISTER 150 -#define TK_VECTOR 151 -#define TK_SELECT_COLUMN 152 -#define TK_IF_NULL_ROW 153 -#define TK_ASTERISK 154 -#define TK_SPAN 155 -#define TK_END_OF_FILE 156 -#define TK_UNCLOSED_STRING 157 -#define TK_SPACE 158 -#define TK_ILLEGAL 159 +#define TK_DO 61 +#define TK_FOR 62 +#define TK_IGNORE 63 +#define TK_INITIALLY 64 +#define TK_INSTEAD 65 +#define TK_NO 66 +#define TK_KEY 67 +#define TK_OF 68 +#define TK_OFFSET 69 +#define TK_PRAGMA 70 +#define TK_RAISE 71 +#define TK_RECURSIVE 72 +#define TK_REPLACE 73 +#define TK_RESTRICT 74 +#define TK_ROW 75 +#define TK_TRIGGER 76 +#define TK_VACUUM 77 +#define TK_VIEW 78 +#define TK_VIRTUAL 79 +#define TK_WITH 80 +#define TK_REINDEX 81 +#define TK_RENAME 82 +#define TK_CTIME_KW 83 +#define TK_ANY 84 +#define TK_BITAND 85 +#define TK_BITOR 86 +#define TK_LSHIFT 87 +#define TK_RSHIFT 88 +#define TK_PLUS 89 +#define TK_MINUS 90 +#define TK_STAR 91 +#define TK_SLASH 92 +#define TK_REM 93 +#define TK_CONCAT 94 +#define TK_COLLATE 95 +#define TK_BITNOT 96 +#define TK_ON 97 +#define TK_INDEXED 98 +#define TK_STRING 99 +#define TK_JOIN_KW 100 +#define TK_CONSTRAINT 101 +#define TK_DEFAULT 102 +#define TK_NULL 103 +#define TK_PRIMARY 104 +#define TK_UNIQUE 105 +#define TK_CHECK 106 +#define TK_REFERENCES 107 +#define TK_AUTOINCR 108 +#define TK_INSERT 109 +#define TK_DELETE 110 +#define TK_UPDATE 111 +#define TK_SET 112 +#define TK_DEFERRABLE 113 +#define TK_FOREIGN 114 +#define TK_DROP 115 +#define TK_UNION 116 +#define TK_ALL 117 +#define TK_EXCEPT 118 +#define TK_INTERSECT 119 +#define TK_SELECT 120 +#define TK_VALUES 121 +#define TK_DISTINCT 122 +#define TK_DOT 123 +#define TK_FROM 124 +#define TK_JOIN 125 +#define TK_USING 126 +#define TK_ORDER 127 +#define TK_GROUP 128 +#define TK_HAVING 129 +#define TK_LIMIT 130 +#define TK_WHERE 131 +#define TK_INTO 132 +#define TK_NOTHING 133 +#define TK_FLOAT 134 +#define TK_BLOB 135 +#define TK_INTEGER 136 +#define TK_VARIABLE 137 +#define TK_CASE 138 +#define TK_WHEN 139 +#define TK_THEN 140 +#define TK_ELSE 141 +#define TK_INDEX 142 +#define TK_ALTER 143 +#define TK_ADD 144 +#define TK_TRUEFALSE 145 +#define TK_ISNOT 146 +#define TK_FUNCTION 147 +#define TK_COLUMN 148 +#define TK_AGG_FUNCTION 149 +#define TK_AGG_COLUMN 150 +#define TK_UMINUS 151 +#define TK_UPLUS 152 +#define TK_TRUTH 153 +#define TK_REGISTER 154 +#define TK_VECTOR 155 +#define TK_SELECT_COLUMN 156 +#define TK_IF_NULL_ROW 157 +#define TK_ASTERISK 158 +#define TK_SPAN 159 +#define TK_END_OF_FILE 160 +#define TK_UNCLOSED_STRING 161 +#define TK_SPACE 162 +#define TK_ILLEGAL 163 /* The token codes above must all fit in 8 bits */ #define TKFLG_MASK 0xff @@ -12710,6 +13424,13 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define SQLITE_DEFAULT_PCACHE_INITSZ 20 #endif +/* +** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option. +*/ +#ifndef SQLITE_DEFAULT_SORTERREF_SIZE +# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff +#endif + /* ** The compile-time options SQLITE_MMAP_READWRITE and ** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another. @@ -13034,9 +13755,10 @@ typedef INT16_TYPE LogEst; */ typedef struct BusyHandler BusyHandler; struct BusyHandler { - int (*xFunc)(void *,int); /* The busy callback */ - void *pArg; /* First arg to busy callback */ - int nBusy; /* Incremented with each busy call */ + int (*xBusyHandler)(void *,int); /* The busy callback */ + void *pBusyArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ + u8 bExtraFileArg; /* Include sqlite3_file as callback arg */ }; /* @@ -13136,7 +13858,6 @@ typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; -typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; @@ -13159,7 +13880,7 @@ typedef struct Select Select; typedef struct SQLiteThread SQLiteThread; typedef struct SelectDest SelectDest; typedef struct SrcList SrcList; -typedef struct StrAccum StrAccum; +typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */ typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; @@ -13168,6 +13889,7 @@ typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; +typedef struct Upsert Upsert; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; @@ -13450,13 +14172,28 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); ** entry in either an index or table btree. ** ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain -** an arbitrary key and no data. These btrees have pKey,nKey set to their -** key and pData,nData,nZero set to zero. +** an arbitrary key and no data. These btrees have pKey,nKey set to the +** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem +** fields give an array of Mem objects that are a decomposition of the key. +** The nMem field might be zero, indicating that no decomposition is available. ** ** Table btrees (used for rowid tables) contain an integer rowid used as ** the key and passed in the nKey field. The pKey field is zero. ** pData,nData hold the content of the new entry. nZero extra zero bytes ** are appended to the end of the content when constructing the entry. +** The aMem,nMem fields are uninitialized for table btrees. +** +** Field usage summary: +** +** Table BTrees Index Btrees +** +** pKey always NULL encoded key +** nKey the ROWID length of pKey +** pData data not used +** aMem not used decomposed key value +** nMem not used entries in aMem +** nData length of pData not used +** nZero extra zeros after pData not used ** ** This object is used to pass information into sqlite3BtreeInsert(). The ** same information used to be passed as five separate parameters. But placing @@ -13467,7 +14204,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ - const void *pData; /* Data for tables. NULL for indexes */ + const void *pData; /* Data for tables. */ sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */ u16 nMem; /* Number of aMem[] value. Might be zero */ int nData; /* Size of pData. 0 if none. */ @@ -13482,6 +14219,9 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); +#endif SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); @@ -13695,6 +14435,7 @@ typedef struct VdbeOpList VdbeOpList; #define P4_INT64 (-14) /* P4 is a 64-bit signed integer */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ +#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -13821,90 +14562,94 @@ typedef struct VdbeOpList VdbeOpList; #define OP_RealAffinity 81 #define OP_Cast 82 /* synopsis: affinity(r[P1]) */ #define OP_Permutation 83 -#define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ -#define OP_Column 96 /* synopsis: r[P3]=PX */ -#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 100 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 101 -#define OP_SetCookie 102 -#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenDup 106 -#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 109 -#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 112 -#define OP_ColumnsUsed 113 -#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ -#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 118 -#define OP_ResetCount 119 -#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 121 /* synopsis: r[P2]=data */ -#define OP_RowData 122 /* synopsis: r[P2]=data */ -#define OP_Rowid 123 /* synopsis: r[P2]=rowid */ -#define OP_NullRow 124 -#define OP_SeekEnd 125 -#define OP_SorterInsert 126 /* synopsis: key=r[P2] */ -#define OP_IdxInsert 127 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 128 /* synopsis: key=r[P2@P3] */ -#define OP_DeferredSeek 129 /* synopsis: Move P3 to P1.rowid if needed */ -#define OP_IdxRowid 130 /* synopsis: r[P2]=rowid */ -#define OP_Destroy 131 -#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_Clear 133 -#define OP_ResetSorter 134 -#define OP_CreateBtree 135 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ -#define OP_SqlExec 136 -#define OP_ParseSchema 137 -#define OP_LoadAnalysis 138 -#define OP_DropTable 139 -#define OP_DropIndex 140 -#define OP_DropTrigger 141 -#define OP_IntegrityCk 142 -#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 144 -#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 151 -#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 153 -#define OP_VCreate 154 -#define OP_VDestroy 155 -#define OP_VOpen 156 -#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 158 -#define OP_Pagecount 159 -#define OP_MaxPgcnt 160 -#define OP_PureFunc0 161 -#define OP_Function0 162 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_PureFunc 163 -#define OP_Function 164 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_CursorHint 165 -#define OP_Noop 166 -#define OP_Explain 167 +#define OP_Compare 84 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ +#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +#define OP_IsTrue 95 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ +#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +#define OP_Offset 97 /* synopsis: r[P3] = sqlite_offset(P1) */ +#define OP_Column 98 /* synopsis: r[P3]=PX */ +#define OP_String8 99 /* same as TK_STRING, synopsis: r[P2]='P4' */ +#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 102 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 103 +#define OP_SetCookie 104 +#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenDup 108 +#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 111 +#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 114 +#define OP_ColumnsUsed 115 +#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */ +#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 120 +#define OP_ResetCount 121 +#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 123 /* synopsis: r[P2]=data */ +#define OP_RowData 124 /* synopsis: r[P2]=data */ +#define OP_Rowid 125 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 126 +#define OP_SeekEnd 127 +#define OP_SorterInsert 128 /* synopsis: key=r[P2] */ +#define OP_IdxInsert 129 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 130 /* synopsis: key=r[P2@P3] */ +#define OP_DeferredSeek 131 /* synopsis: Move P3 to P1.rowid if needed */ +#define OP_IdxRowid 132 /* synopsis: r[P2]=rowid */ +#define OP_Destroy 133 +#define OP_Real 134 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_Clear 135 +#define OP_ResetSorter 136 +#define OP_CreateBtree 137 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +#define OP_SqlExec 138 +#define OP_ParseSchema 139 +#define OP_LoadAnalysis 140 +#define OP_DropTable 141 +#define OP_DropIndex 142 +#define OP_DropTrigger 143 +#define OP_IntegrityCk 144 +#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 146 +#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 153 +#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 155 +#define OP_VCreate 156 +#define OP_VDestroy 157 +#define OP_VOpen 158 +#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 160 +#define OP_Pagecount 161 +#define OP_MaxPgcnt 162 +#define OP_PureFunc0 163 +#define OP_Function0 164 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_PureFunc 165 +#define OP_Function 166 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Trace 167 +#define OP_CursorHint 168 +#define OP_Noop 169 +#define OP_Explain 170 +#define OP_Abortable 171 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -13927,18 +14672,18 @@ typedef struct VdbeOpList VdbeOpList; /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\ /* 64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\ /* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ -/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\ -/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ -/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x00, 0x26, 0x26, 0x26,\ +/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x12,\ +/* 96 */ 0x12, 0x20, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10,\ /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ -/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04,\ -/* 128 */ 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10,\ -/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ -/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ -/* 160 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -} +/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\ +/* 128 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ +/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 168 */ 0x00, 0x00, 0x00, 0x00,} /* The sqlite3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -13980,7 +14725,24 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); # define sqlite3VdbeVerifyNoMallocRequired(A,B) # define sqlite3VdbeVerifyNoResultRow(A) #endif -SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); +#if defined(SQLITE_DEBUG) +SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); +#else +# define sqlite3VdbeVerifyAbortable(A,B) +#endif +SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); +#ifndef SQLITE_OMIT_EXPLAIN +SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); +SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); +SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); +# define ExplainQueryPlan(P) sqlite3VdbeExplain P +# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) +# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) +#else +# define ExplainQueryPlan(P) +# define ExplainQueryPlanPop(P) +# define ExplainQueryPlanParent(P) 0 +#endif SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); @@ -14003,6 +14765,9 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int); +#endif SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); @@ -14239,7 +15004,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); #ifdef SQLITE_HAS_CODEC SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); @@ -14325,6 +15090,11 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager); +#else +# define sqlite3PagerResetLockTimeout(X) +#endif /* Functions used to truncate the database file. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); @@ -15132,7 +15902,7 @@ struct sqlite3 { u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ - u8 skipBtreeMutex; /* True if no shared-cache backends */ + u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ @@ -15144,8 +15914,9 @@ struct sqlite3 { int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ - u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ - u8 imposterTable; /* Building an imposter table */ + unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ + unsigned imposterTable : 1; /* Building an imposter table */ + unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ @@ -15198,7 +15969,7 @@ struct sqlite3 { Hash aModule; /* populated by sqlite3_create_module() */ VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ VTable **aVTrans; /* Virtual tables with open transactions */ - VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ + VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ #endif Hash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ @@ -15273,7 +16044,10 @@ struct sqlite3 { #define SQLITE_QueryOnly 0x00100000 /* Disable database changes */ #define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */ #define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ -#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee */ +#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ +#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ +#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ + /* Flags used only if debugging */ #ifdef SQLITE_DEBUG #define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ @@ -15289,6 +16063,7 @@ struct sqlite3 { #define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ #define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ #define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ +#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -15308,6 +16083,8 @@ struct sqlite3 { #define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ +#define SQLITE_PushDown 0x1000 /* The push-down optimization */ +#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* @@ -15406,6 +16183,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ +#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -15530,6 +16308,8 @@ struct Column { #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ +#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ +#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ /* ** A "Collating Sequence" is defined by an instance of the following @@ -15817,13 +16597,12 @@ struct FKey { #define OE_Fail 3 /* Stop the operation but leave all prior changes */ #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ - -#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ -#define OE_SetNull 7 /* Set the foreign key value to NULL */ -#define OE_SetDflt 8 /* Set the foreign key value to its default */ -#define OE_Cascade 9 /* Cascade the changes */ - -#define OE_Default 10 /* Do whatever the default action is */ +#define OE_Update 6 /* Process as a DO UPDATE in an upsert */ +#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 8 /* Set the foreign key value to NULL */ +#define OE_SetDflt 9 /* Set the foreign key value to its default */ +#define OE_Cascade 10 /* Cascade the changes */ +#define OE_Default 11 /* Do whatever the default action is */ /* @@ -15950,6 +16729,7 @@ struct Index { unsigned isCovering:1; /* True if this is a covering index */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ + unsigned bNoQuery:1; /* Do not use this index to optimize queries */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ @@ -16180,7 +16960,7 @@ struct Expr { */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ - /* 0x000004 // available for use */ +#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ /* 0x000008 // available for use */ #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ @@ -16204,9 +16984,10 @@ struct Expr { #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ /* -** Combinations of two or more EP_* flags +** The EP_Propagate mask is a set of properties that automatically propagate +** upwards into parent nodes. */ -#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ +#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc) /* ** These macros can be used to test, set, or clear bits in the @@ -16268,6 +17049,7 @@ struct ExprList { unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ unsigned reusable :1; /* Constant expression is reusable */ + unsigned bSorterRef :1; /* Defer evaluation until after sorting */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -16278,17 +17060,6 @@ struct ExprList { } a[1]; /* One slot for each expression in the list */ }; -/* -** An instance of this structure is used by the parser to record both -** the parse tree for an expression and the span of input text for an -** expression. -*/ -struct ExprSpan { - Expr *pExpr; /* The expression parse tree */ - const char *zStart; /* First character of input text */ - const char *zEnd; /* One character past the end of input text */ -}; - /* ** An instance of this structure can hold a simple list of identifiers, ** such as the list "a,b,c" in the following statements: @@ -16378,9 +17149,6 @@ struct SrcList { unsigned viaCoroutine :1; /* Implemented as a co-routine */ unsigned isRecursive :1; /* True for recursive reference in WITH */ } fg; -#ifndef SQLITE_OMIT_EXPLAIN - u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ -#endif int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ @@ -16462,8 +17230,11 @@ struct SrcList { struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ - ExprList *pEList; /* Optional list of result-set columns */ - AggInfo *pAggInfo; /* Information about aggregates at this level */ + union { + ExprList *pEList; /* Optional list of result-set columns */ + AggInfo *pAggInfo; /* Information about aggregates at this level */ + Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ + } uNC; NameContext *pNext; /* Next outer name context. NULL for outermost */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ @@ -16485,17 +17256,48 @@ struct NameContext { #define NC_HasAgg 0x0010 /* One or more aggregate functions seen */ #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ #define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ +#define NC_UEList 0x0080 /* True if uNC.pEList is used */ +#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */ +#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */ #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ +#define NC_Complex 0x2000 /* True if a function or subquery seen */ + +/* +** An instance of the following object describes a single ON CONFLICT +** clause in an upsert. +** +** The pUpsertTarget field is only set if the ON CONFLICT clause includes +** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the +** conflict-target clause.) The pUpsertTargetWhere is the optional +** WHERE clause used to identify partial unique indexes. +** +** pUpsertSet is the list of column=expr terms of the UPDATE statement. +** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The +** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the +** WHERE clause is omitted. +*/ +struct Upsert { + ExprList *pUpsertTarget; /* Optional description of conflicting index */ + Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */ + ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */ + Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ + /* The fields above comprise the parse tree for the upsert clause. + ** The fields below are used to transfer information from the INSERT + ** processing down into the UPDATE processing while generating code. + ** Upsert owns the memory allocated above, but not the memory below. */ + Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */ + SrcList *pUpsertSrc; /* Table to be updated */ + int regData; /* First register holding array of VALUES */ + int iDataCur; /* Index of the data cursor */ + int iIdxCur; /* Index of the first index cursor */ +}; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** -** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. -** If there is a LIMIT clause, the parser sets nLimit to the value of the -** limit and nOffset to the value of the offset (or 0 if there is not -** offset). But later on, nLimit and nOffset become the memory locations -** in the VDBE that record the limit and offset counters. +** See the header comment on the computeLimitRegisters() routine for a +** detailed description of the meaning of the iLimit and iOffset fields. ** ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. ** These addresses must be stored so that we can go back and fill in @@ -16525,7 +17327,6 @@ struct Select { Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ - Expr *pOffset; /* OFFSET expression. NULL means not used. */ With *pWith; /* WITH clause attached to this select. Or NULL. */ }; @@ -16556,7 +17357,7 @@ struct Select { #define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ #define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ - +#define SF_ComplexResult 0x40000 /* Result contains subquery or function */ /* ** The results of a SELECT can be distributed in several ways, as defined @@ -16760,7 +17561,7 @@ struct Parse { int nMem; /* Number of memory cells used so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int iSelfTab; /* Table for associated with an index on expr, or negative + int iSelfTab; /* Table associated with an index on expr, or negative ** of the base register during check-constraint eval */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ @@ -16775,7 +17576,6 @@ struct Parse { int nMaxArg; /* Max args passed to user function by sub-program */ #if SELECTTRACE_ENABLED int nSelect; /* Number of SELECT statements seen */ - int nSelectIndent; /* How far to indent SELECTTRACE() output */ #endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ @@ -16827,8 +17627,7 @@ struct Parse { #endif int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN - int iSelectId; /* ID of current select for EXPLAIN output */ - int iNextSelectId; /* Next available select ID for EXPLAIN output */ + int addrExplain; /* Address of current OP_Explain opcode */ #endif VList *pVList; /* Mapping between variable names and numbers */ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ @@ -16901,6 +17700,7 @@ struct AuthContext { #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ +#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */ /* * Each trigger present in the database schema is stored as an instance of @@ -16986,8 +17786,10 @@ struct TriggerStep { Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ - ExprList *pExprList; /* SET clause for UPDATE. */ + ExprList *pExprList; /* SET clause for UPDATE */ IdList *pIdList; /* Column names for INSERT */ + Upsert *pUpsert; /* Upsert clauses on an INSERT */ + char *zSpan; /* Original SQL text of this command */ TriggerStep *pNext; /* Next in the link-list */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ }; @@ -17011,17 +17813,15 @@ struct DbFixer { ** An objected used to accumulate the text of a string where we ** do not necessarily know how big the string will be in the end. */ -struct StrAccum { +struct sqlite3_str { sqlite3 *db; /* Optional database for lookaside. Can be NULL */ char *zText; /* The string collected so far */ u32 nAlloc; /* Amount of space allocated in zText */ u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ u32 nChar; /* Length of the string so far */ - u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ + u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */ u8 printfFlags; /* SQLITE_PRINTF flags below */ }; -#define STRACCUM_NOMEM 1 -#define STRACCUM_TOOBIG 2 #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ #define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ @@ -17098,6 +17898,7 @@ struct Sqlite3Config { #endif int bLocaltimeFault; /* True to fail localtime() calls */ int iOnceResetThreshold; /* When to reset OP_Once counters */ + u32 szSorterRef; /* Min size in bytes to use sorter-refs */ }; /* @@ -17137,9 +17938,9 @@ struct Walker { struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ - struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */ + struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ ExprList *pGroupBy; /* GROUP BY clause */ - struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */ + Select *pSelect; /* HAVING to WHERE clause ctx */ } u; }; @@ -17207,6 +18008,7 @@ struct TreeView { ** using sqlite3_log(). The routines also provide a convenient place ** to set a debugger breakpoint. */ +SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType); SQLITE_PRIVATE int sqlite3CorruptError(int); SQLITE_PRIVATE int sqlite3MisuseError(int); SQLITE_PRIVATE int sqlite3CantopenError(int); @@ -17297,6 +18099,7 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); +SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3*,const char*,const char*); SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); @@ -17365,6 +18168,12 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); +#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT) +SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); +#else +# define sqlite3MutexWarnOnContention(x) +#endif + #ifndef SQLITE_OMIT_FLOATING_POINT SQLITE_PRIVATE int sqlite3IsNaN(double); #else @@ -17381,8 +18190,6 @@ struct PrintfArguments { sqlite3_value **apArg; /* The argument values */ }; -SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) @@ -17429,7 +18236,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); -SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); +SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); @@ -17459,7 +18266,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*); SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, @@ -17510,7 +18317,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif -SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); +SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); @@ -17531,16 +18338,17 @@ SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,i SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, - Expr*,ExprList*,u32,Expr*,Expr*); + Expr*,ExprList*,u32,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) -SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); +SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif -SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); -SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); +SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); +SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, + Upsert*); SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); @@ -17595,6 +18403,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); @@ -17612,6 +18421,8 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); +SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); +SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); @@ -17630,7 +18441,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int* SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, - u8,u8,int,int*,int*); + u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); #else @@ -17664,7 +18475,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int); +SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); #endif #ifndef SQLITE_OMIT_TRIGGER @@ -17680,11 +18491,15 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, i SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, + const char*,const char*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, - Select*,u8); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); + Select*,u8,Upsert*, + const char*,const char*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8, + const char*,const char*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*, + const char*,const char*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); @@ -17791,6 +18606,10 @@ SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif +#ifdef SQLITE_ENABLE_DESERIALIZE +SQLITE_PRIVATE int sqlite3MemdbInit(void); +#endif + SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); @@ -17839,6 +18658,9 @@ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; SQLITE_PRIVATE int sqlite3PendingByte; #endif #endif +#ifdef VDBE_PROFILE +SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt; +#endif SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int); SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); @@ -17859,9 +18681,9 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); -SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); +SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); @@ -17884,17 +18706,14 @@ SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); +SQLITE_PRIVATE void sqlite3NoopDestructor(void*); SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); -SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); -SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); -SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); -SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); @@ -17921,10 +18740,10 @@ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); +SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*); SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); #endif -SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); +SQLITE_PRIVATE void sqlite3Parser(void*, int, Token); #ifdef YYTRACKMAXSTACKDEPTH SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); #endif @@ -17990,7 +18809,6 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); -SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); @@ -18012,6 +18830,18 @@ SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8); #define sqlite3WithPush(x,y,z) #define sqlite3WithDelete(x,y) #endif +#ifndef SQLITE_OMIT_UPSERT +SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*); +SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); +SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); +SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); +SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); +#else +#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0) +#define sqlite3UpsertDelete(x,y) +#define sqlite3UpsertDup(x,y) ((Upsert*)0) +#endif + /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign @@ -18114,6 +18944,9 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); #endif +#if defined(YYCOVERAGE) +SQLITE_PRIVATE int sqlite3ParserCoverage(FILE*); +#endif /* ** If the SQLITE_ENABLE IOTRACE exists then the global variable @@ -18441,7 +19274,8 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ - 0x7ffffffe /* iOnceResetThreshold */ + 0x7ffffffe, /* iOnceResetThreshold */ + SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ }; /* @@ -18459,6 +19293,13 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = { { "1", 1 } }; +#ifdef VDBE_PROFILE +/* +** The following performance counter can be used in place of +** sqlite3Hwtime() for profiling. This is a no-op on standard builds. +*/ +SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; +#endif /* ** The value of the "pending" byte must be 0x40000000 (1 byte past the @@ -18835,7 +19676,6 @@ struct sqlite3_context { int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ u8 skipFlag; /* Skip accumulator loading if true */ - u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ u8 argc; /* Number of arguments */ sqlite3_value *argv[1]; /* Argument set */ }; @@ -18898,6 +19738,7 @@ struct Vdbe { int nOp; /* Number of instructions in the program */ #ifdef SQLITE_DEBUG int rcApp; /* errcode set by sqlite3_result_error_code() */ + u32 nWrite; /* Number of write operations that have occurred */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ @@ -19005,6 +19846,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); +SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); @@ -19032,6 +19874,14 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); +SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); +#else +# define sqlite3VdbeIncrWriteCounter(V,C) +# define sqlite3VdbeAssertAbortable(V) +#endif + #if !defined(SQLITE_OMIT_SHARED_CACHE) SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); #else @@ -19398,6 +20248,9 @@ SQLITE_API int sqlite3_db_status( ** pagers the database handle is connected to. *pHighwater is always set ** to zero. */ + case SQLITE_DBSTATUS_CACHE_SPILL: + op = SQLITE_DBSTATUS_CACHE_WRITE+1; + /* Fall through into the next case */ case SQLITE_DBSTATUS_CACHE_HIT: case SQLITE_DBSTATUS_CACHE_MISS: case SQLITE_DBSTATUS_CACHE_WRITE:{ @@ -19480,7 +20333,7 @@ SQLITE_API int sqlite3_db_status( ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 -** ISBM 0-943396-61-1 +** ISBN 0-943396-61-1 ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ @@ -20818,8 +21671,11 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ ** routine has no return value since the return value would be meaningless. */ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + if( id->pMethods==0 ) return SQLITE_NOTFOUND; #ifdef SQLITE_TEST - if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO + && op!=SQLITE_FCNTL_LOCK_TIMEOUT + ){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite ** is using a regular VFS, it is called after the corresponding ** transaction has been committed. Injecting a fault at this point @@ -20836,7 +21692,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ return id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ - (void)id->pMethods->xFileControl(id, op, pArg); + if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ @@ -23385,6 +24241,193 @@ static SQLITE_WSD int mutexIsInit = 0; #ifndef SQLITE_MUTEX_OMIT + +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS +/* +** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains +** the implementation of a wrapper around the system default mutex +** implementation (sqlite3DefaultMutex()). +** +** Most calls are passed directly through to the underlying default +** mutex implementation. Except, if a mutex is configured by calling +** sqlite3MutexWarnOnContention() on it, then if contention is ever +** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). +** +** This type of mutex is used as the database handle mutex when testing +** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. +*/ + +/* +** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS +** is defined. Variable CheckMutex.mutex is a pointer to the real mutex +** allocated by the system mutex implementation. Variable iType is usually set +** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST +** or one of the static mutex identifiers. Or, if this is a recursive mutex +** that has been configured using sqlite3MutexWarnOnContention(), it is +** set to SQLITE_MUTEX_WARNONCONTENTION. +*/ +typedef struct CheckMutex CheckMutex; +struct CheckMutex { + int iType; + sqlite3_mutex *mutex; +}; + +#define SQLITE_MUTEX_WARNONCONTENTION (-1) + +/* +** Pointer to real mutex methods object used by the CheckMutex +** implementation. Set by checkMutexInit(). +*/ +static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods; + +#ifdef SQLITE_DEBUG +static int checkMutexHeld(sqlite3_mutex *p){ + return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex); +} +static int checkMutexNotheld(sqlite3_mutex *p){ + return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex); +} +#endif + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int checkMutexInit(void){ + pGlobalMutexMethods = sqlite3DefaultMutex(); + return SQLITE_OK; +} +static int checkMutexEnd(void){ + pGlobalMutexMethods = 0; + return SQLITE_OK; +} + +/* +** Allocate a mutex. +*/ +static sqlite3_mutex *checkMutexAlloc(int iType){ + static CheckMutex staticMutexes[] = { + {2, 0}, {3, 0}, {4, 0}, {5, 0}, + {6, 0}, {7, 0}, {8, 0}, {9, 0}, + {10, 0}, {11, 0}, {12, 0}, {13, 0} + }; + CheckMutex *p = 0; + + assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 ); + if( iType<2 ){ + p = sqlite3MallocZero(sizeof(CheckMutex)); + if( p==0 ) return 0; + p->iType = iType; + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + if( iType-2>=ArraySize(staticMutexes) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + p = &staticMutexes[iType-2]; + } + + if( p->mutex==0 ){ + p->mutex = pGlobalMutexMethods->xMutexAlloc(iType); + if( p->mutex==0 ){ + if( iType<2 ){ + sqlite3_free(p); + } + p = 0; + } + } + + return (sqlite3_mutex*)p; +} + +/* +** Free a mutex. +*/ +static void checkMutexFree(sqlite3_mutex *p){ + assert( SQLITE_MUTEX_RECURSIVE<2 ); + assert( SQLITE_MUTEX_FAST<2 ); + assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); + +#if SQLITE_ENABLE_API_ARMOR + if( ((CheckMutex*)p)->iType<2 ) +#endif + { + CheckMutex *pCheck = (CheckMutex*)p; + pGlobalMutexMethods->xMutexFree(pCheck->mutex); + sqlite3_free(pCheck); + } +#ifdef SQLITE_ENABLE_API_ARMOR + else{ + (void)SQLITE_MISUSE_BKPT; + } +#endif +} + +/* +** Enter the mutex. +*/ +static void checkMutexEnter(sqlite3_mutex *p){ + CheckMutex *pCheck = (CheckMutex*)p; + if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){ + if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){ + return; + } + sqlite3_log(SQLITE_MISUSE, + "illegal multi-threaded access to database connection" + ); + } + pGlobalMutexMethods->xMutexEnter(pCheck->mutex); +} + +/* +** Enter the mutex (do not block). +*/ +static int checkMutexTry(sqlite3_mutex *p){ + CheckMutex *pCheck = (CheckMutex*)p; + return pGlobalMutexMethods->xMutexTry(pCheck->mutex); +} + +/* +** Leave the mutex. +*/ +static void checkMutexLeave(sqlite3_mutex *p){ + CheckMutex *pCheck = (CheckMutex*)p; + pGlobalMutexMethods->xMutexLeave(pCheck->mutex); +} + +sqlite3_mutex_methods const *multiThreadedCheckMutex(void){ + static const sqlite3_mutex_methods sMutex = { + checkMutexInit, + checkMutexEnd, + checkMutexAlloc, + checkMutexFree, + checkMutexEnter, + checkMutexTry, + checkMutexLeave, +#ifdef SQLITE_DEBUG + checkMutexHeld, + checkMutexNotheld +#else + 0, + 0 +#endif + }; + return &sMutex; +} + +/* +** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as +** one on which there should be no contention. +*/ +SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ + if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){ + CheckMutex *pCheck = (CheckMutex*)p; + assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE ); + pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; + } +} +#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ + /* ** Initialize the mutex system. */ @@ -23400,7 +24443,11 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){ sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; if( sqlite3GlobalConfig.bCoreMutex ){ +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS + pFrom = multiThreadedCheckMutex(); +#else pFrom = sqlite3DefaultMutex(); +#endif }else{ pFrom = sqlite3NoopMutex(); } @@ -23799,11 +24846,12 @@ struct sqlite3_mutex { #endif }; #if SQLITE_MUTEX_NREF -#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0} +# define SQLITE3_MUTEX_INITIALIZER(id) \ + {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0} #elif defined(SQLITE_ENABLE_API_ARMOR) -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 } +# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id } #else -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER } #endif /* @@ -23900,18 +24948,18 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; } */ static sqlite3_mutex *pthreadMutexAlloc(int iType){ static sqlite3_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER + SQLITE3_MUTEX_INITIALIZER(2), + SQLITE3_MUTEX_INITIALIZER(3), + SQLITE3_MUTEX_INITIALIZER(4), + SQLITE3_MUTEX_INITIALIZER(5), + SQLITE3_MUTEX_INITIALIZER(6), + SQLITE3_MUTEX_INITIALIZER(7), + SQLITE3_MUTEX_INITIALIZER(8), + SQLITE3_MUTEX_INITIALIZER(9), + SQLITE3_MUTEX_INITIALIZER(10), + SQLITE3_MUTEX_INITIALIZER(11), + SQLITE3_MUTEX_INITIALIZER(12), + SQLITE3_MUTEX_INITIALIZER(13) }; sqlite3_mutex *p; switch( iType ){ @@ -23929,6 +24977,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); +#endif +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + p->id = SQLITE_MUTEX_RECURSIVE; #endif } break; @@ -23937,6 +24988,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ p = sqlite3MallocZero( sizeof(*p) ); if( p ){ pthread_mutex_init(&p->mutex, 0); +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + p->id = SQLITE_MUTEX_FAST; +#endif } break; } @@ -23952,7 +25006,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ } } #if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - if( p ) p->id = iType; + assert( p==0 || p->id==iType ); #endif return p; } @@ -24469,7 +25523,7 @@ struct sqlite3_mutex { #ifdef SQLITE_DEBUG volatile int nRef; /* Number of enterances */ volatile DWORD owner; /* Thread holding this mutex */ - volatile int trace; /* True to trace changes */ + volatile LONG trace; /* True to trace changes */ #endif }; @@ -24481,10 +25535,10 @@ struct sqlite3_mutex { #define SQLITE_W32_MUTEX_INITIALIZER { 0 } #ifdef SQLITE_DEBUG -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ +#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ 0L, (DWORD)0, 0 } #else -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } +#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } #endif #ifdef SQLITE_DEBUG @@ -24527,18 +25581,18 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ ** Initialize and deinitialize the mutex subsystem. */ static sqlite3_mutex winMutex_staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER + SQLITE3_MUTEX_INITIALIZER(2), + SQLITE3_MUTEX_INITIALIZER(3), + SQLITE3_MUTEX_INITIALIZER(4), + SQLITE3_MUTEX_INITIALIZER(5), + SQLITE3_MUTEX_INITIALIZER(6), + SQLITE3_MUTEX_INITIALIZER(7), + SQLITE3_MUTEX_INITIALIZER(8), + SQLITE3_MUTEX_INITIALIZER(9), + SQLITE3_MUTEX_INITIALIZER(10), + SQLITE3_MUTEX_INITIALIZER(11), + SQLITE3_MUTEX_INITIALIZER(12), + SQLITE3_MUTEX_INITIALIZER(13) }; static int winMutex_isInit = 0; @@ -24668,15 +25722,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){ } #endif p = &winMutex_staticMutexes[iType-2]; - p->id = iType; #ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC - p->trace = 1; + InterlockedCompareExchange(&p->trace, 1, 0); #endif #endif break; } } + assert( p==0 || p->id==iType ); return p; } @@ -25458,6 +26512,19 @@ SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ return zNew; } +/* +** The text between zStart and zEnd represents a phrase within a larger +** SQL statement. Make a copy of this phrase in space obtained form +** sqlite3DbMalloc(). Omit leading and trailing whitespace. +*/ +SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ + int n; + while( sqlite3Isspace(zStart[0]) ) zStart++; + n = (int)(zEnd - zStart); + while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--; + return sqlite3DbStrNDup(db, zStart, n); +} + /* ** Free any prior content in *pz and replace it with a copy of zNew. */ @@ -25670,7 +26737,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ ** Set the StrAccum object to an error mode. */ static void setStrAccumError(StrAccum *p, u8 eError){ - assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); + assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); p->accError = eError; p->nAlloc = 0; } @@ -25704,8 +26771,8 @@ static char *getTextArg(PrintfArguments *p){ /* ** Render a string given by "fmt" into the StrAccum object. */ -SQLITE_PRIVATE void sqlite3VXPrintf( - StrAccum *pAccum, /* Accumulate results here */ +SQLITE_API void sqlite3_str_vappendf( + sqlite3_str *pAccum, /* Accumulate results here */ const char *fmt, /* Format string */ va_list ap /* arguments */ ){ @@ -25742,6 +26809,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ + /* pAccum never starts out with an empty buffer that was obtained from + ** malloc(). This precondition is required by the mprintf("%z...") + ** optimization. */ + assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); + bufpt = 0; if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ pArgList = va_arg(ap, PrintfArguments*); @@ -25757,11 +26829,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( #else do{ fmt++; }while( *fmt && *fmt != '%' ); #endif - sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); + sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); if( *fmt==0 ) break; } if( (c=(*++fmt))==0 ){ - sqlite3StrAccumAppend(pAccum, "%", 1); + sqlite3_str_append(pAccum, "%", 1); break; } /* Find out what flags are present */ @@ -25939,7 +27011,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( u64 n = (u64)precision + 10 + precision/3; zOut = zExtra = sqlite3Malloc( n ); if( zOut==0 ){ - setStrAccumError(pAccum, STRACCUM_NOMEM); + setStrAccumError(pAccum, SQLITE_NOMEM); return; } nOut = (int)n; @@ -26064,7 +27136,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); if( bufpt==0 ){ - setStrAccumError(pAccum, STRACCUM_NOMEM); + setStrAccumError(pAccum, SQLITE_NOMEM); return; } } @@ -26160,22 +27232,52 @@ SQLITE_PRIVATE void sqlite3VXPrintf( case etCHARX: if( bArgList ){ bufpt = getTextArg(pArgList); - c = bufpt ? bufpt[0] : 0; + length = 1; + if( bufpt ){ + buf[0] = c = *(bufpt++); + if( (c&0xc0)==0xc0 ){ + while( length<4 && (bufpt[0]&0xc0)==0x80 ){ + buf[length++] = *(bufpt++); + } + } + }else{ + buf[0] = 0; + } }else{ - c = va_arg(ap,int); + unsigned int ch = va_arg(ap,unsigned int); + if( ch<0x00080 ){ + buf[0] = ch & 0xff; + length = 1; + }else if( ch<0x00800 ){ + buf[0] = 0xc0 + (u8)((ch>>6)&0x1f); + buf[1] = 0x80 + (u8)(ch & 0x3f); + length = 2; + }else if( ch<0x10000 ){ + buf[0] = 0xe0 + (u8)((ch>>12)&0x0f); + buf[1] = 0x80 + (u8)((ch>>6) & 0x3f); + buf[2] = 0x80 + (u8)(ch & 0x3f); + length = 3; + }else{ + buf[0] = 0xf0 + (u8)((ch>>18) & 0x07); + buf[1] = 0x80 + (u8)((ch>>12) & 0x3f); + buf[2] = 0x80 + (u8)((ch>>6) & 0x3f); + buf[3] = 0x80 + (u8)(ch & 0x3f); + length = 4; + } } if( precision>1 ){ width -= precision-1; if( width>1 && !flag_leftjustify ){ - sqlite3AppendChar(pAccum, width-1, ' '); + sqlite3_str_appendchar(pAccum, width-1, ' '); width = 0; } - sqlite3AppendChar(pAccum, precision-1, c); + while( precision-- > 1 ){ + sqlite3_str_append(pAccum, buf, length); + } } - length = 1; - buf[0] = c; bufpt = buf; - break; + flag_altform2 = 1; + goto adjust_width_for_utf8; case etSTRING: case etDYNSTRING: if( bArgList ){ @@ -26187,17 +27289,45 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ + if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){ + /* Special optimization for sqlite3_mprintf("%z..."): + ** Extend an existing memory allocation rather than creating + ** a new one. */ + assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); + pAccum->zText = bufpt; + pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); + pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); + pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED; + length = 0; + break; + } zExtra = bufpt; } if( precision>=0 ){ - for(length=0; length 0 && z[0] ){ + SQLITE_SKIP_UTF8(z); + } + length = (int)(z - (unsigned char*)bufpt); + }else{ + for(length=0; length0 ){ + /* Adjust width to account for extra bytes in UTF-8 characters */ + int ii = length - 1; + while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; + } break; - case etSQLESCAPE: /* Escape ' characters */ - case etSQLESCAPE2: /* Escape ' and enclose in '...' */ - case etSQLESCAPE3: { /* Escape " characters */ + case etSQLESCAPE: /* %q: Escape ' characters */ + case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ + case etSQLESCAPE3: { /* %w: Escape " characters */ int i, j, k, n, isnull; int needQuote; char ch; @@ -26211,16 +27341,24 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } isnull = escarg==0; if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); + /* For %q, %Q, and %w, the precision is the number of byte (or + ** characters if the ! flags is present) to use from the input. + ** Because of the extra quoting characters inserted, the number + ** of output characters may be larger than the precision. + */ k = precision; for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ if( ch==q ) n++; + if( flag_altform2 && (ch&0xc0)==0xc0 ){ + while( (escarg[i+1]&0xc0)==0x80 ){ i++; } + } } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 3; if( n>etBUFSIZE ){ bufpt = zExtra = sqlite3Malloc( n ); if( bufpt==0 ){ - setStrAccumError(pAccum, STRACCUM_NOMEM); + setStrAccumError(pAccum, SQLITE_NOMEM); return; } }else{ @@ -26236,10 +27374,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( needQuote ) bufpt[j++] = q; bufpt[j] = 0; length = j; - /* The precision in %q and %Q means how many input characters to - ** consume, not the length of the output... - ** if( precision>=0 && precisionn ){ - sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); + sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; break; @@ -26263,10 +27398,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf( assert( bArgList==0 ); assert( k>=0 && knSrc ); if( pItem->zDatabase ){ - sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); - sqlite3StrAccumAppend(pAccum, ".", 1); + sqlite3_str_appendall(pAccum, pItem->zDatabase); + sqlite3_str_append(pAccum, ".", 1); } - sqlite3StrAccumAppendAll(pAccum, pItem->zName); + sqlite3_str_appendall(pAccum, pItem->zName); length = width = 0; break; } @@ -26278,15 +27413,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf( /* ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do - ** the output. + ** the output. Both length and width are in bytes, not characters, + ** at this point. If the "!" flag was present on string conversions + ** indicating that width and precision should be expressed in characters, + ** then the values have been translated prior to reaching this point. */ width -= length; if( width>0 ){ - if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); - sqlite3StrAccumAppend(pAccum, bufpt, length); - if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); + sqlite3_str_append(pAccum, bufpt, length); + if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); }else{ - sqlite3StrAccumAppend(pAccum, bufpt, length); + sqlite3_str_append(pAccum, bufpt, length); } if( zExtra ){ @@ -26307,13 +27445,13 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ - testcase(p->accError==STRACCUM_TOOBIG); - testcase(p->accError==STRACCUM_NOMEM); + testcase(p->accError==SQLITE_TOOBIG); + testcase(p->accError==SQLITE_NOMEM); return 0; } if( p->mxAlloc==0 ){ N = p->nAlloc - p->nChar - 1; - setStrAccumError(p, STRACCUM_TOOBIG); + setStrAccumError(p, SQLITE_TOOBIG); return N; }else{ char *zOld = isMalloced(p) ? p->zText : 0; @@ -26325,8 +27463,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ szNew += p->nChar; } if( szNew > p->mxAlloc ){ - sqlite3StrAccumReset(p); - setStrAccumError(p, STRACCUM_TOOBIG); + sqlite3_str_reset(p); + setStrAccumError(p, SQLITE_TOOBIG); return 0; }else{ p->nAlloc = (int)szNew; @@ -26343,8 +27481,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ p->nAlloc = sqlite3DbMallocSize(p->db, zNew); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ - sqlite3StrAccumReset(p); - setStrAccumError(p, STRACCUM_NOMEM); + sqlite3_str_reset(p); + setStrAccumError(p, SQLITE_NOMEM); return 0; } } @@ -26354,7 +27492,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ /* ** Append N copies of character c to the given string buffer. */ -SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ +SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ testcase( p->nChar + (i64)N > 0x7fffffff ); if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ return; @@ -26366,9 +27504,9 @@ SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ ** The StrAccum "p" is not large enough to accept N new bytes of z[]. ** So enlarge if first, then do the append. ** -** This is a helper routine to sqlite3StrAccumAppend() that does special-case +** This is a helper routine to sqlite3_str_append() that does special-case ** work (enlarging the buffer) using tail recursion, so that the -** sqlite3StrAccumAppend() routine can use fast calling semantics. +** sqlite3_str_append() routine can use fast calling semantics. */ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ N = sqlite3StrAccumEnlarge(p, N); @@ -26382,7 +27520,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ ** Append N bytes of text from z to the StrAccum object. Increase the ** size of the memory allocation for StrAccum if necessary. */ -SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ +SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ assert( z!=0 || N==0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); @@ -26399,8 +27537,8 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ /* ** Append the complete text of zero-terminated string z[] to the p string. */ -SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ - sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); +SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ + sqlite3_str_append(p, z, sqlite3Strlen30(z)); } @@ -26417,7 +27555,7 @@ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ memcpy(zText, p->zText, p->nChar+1); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ - setStrAccumError(p, STRACCUM_NOMEM); + setStrAccumError(p, SQLITE_NOMEM); } p->zText = zText; return zText; @@ -26432,14 +27570,56 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ return p->zText; } +/* +** This singleton is an sqlite3_str object that is returned if +** sqlite3_malloc() fails to provide space for a real one. This +** sqlite3_str object accepts no new text and always returns +** an SQLITE_NOMEM error. +*/ +static sqlite3_str sqlite3OomStr = { + 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 +}; + +/* Finalize a string created using sqlite3_str_new(). +*/ +SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ + char *z; + if( p!=0 && p!=&sqlite3OomStr ){ + z = sqlite3StrAccumFinish(p); + sqlite3_free(p); + }else{ + z = 0; + } + return z; +} + +/* Return any error code associated with p */ +SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){ + return p ? p->accError : SQLITE_NOMEM; +} + +/* Return the current length of p in bytes */ +SQLITE_API int sqlite3_str_length(sqlite3_str *p){ + return p ? p->nChar : 0; +} + +/* Return the current value for p */ +SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ + if( p==0 || p->nChar==0 ) return 0; + p->zText[p->nChar] = 0; + return p->zText; +} + /* ** Reset an StrAccum string. Reclaim all malloced memory. */ -SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ +SQLITE_API void sqlite3_str_reset(StrAccum *p){ if( isMalloced(p) ){ sqlite3DbFree(p->db, p->zText); p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; } + p->nAlloc = 0; + p->nChar = 0; p->zText = 0; } @@ -26467,6 +27647,18 @@ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, i p->printfFlags = 0; } +/* Allocate and initialize a new dynamic string object */ +SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){ + sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); + if( p ){ + sqlite3StrAccumInit(p, 0, 0, 0, + db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); + }else{ + p = &sqlite3OomStr; + } + return p; +} + /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. @@ -26479,9 +27671,9 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); acc.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3VXPrintf(&acc, zFormat, ap); + sqlite3_str_vappendf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); - if( acc.accError==STRACCUM_NOMEM ){ + if( acc.accError==SQLITE_NOMEM ){ sqlite3OomFault(db); } return z; @@ -26519,7 +27711,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ if( sqlite3_initialize() ) return 0; #endif sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - sqlite3VXPrintf(&acc, zFormat, ap); + sqlite3_str_vappendf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; } @@ -26564,7 +27756,7 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); - sqlite3VXPrintf(&acc, zFormat, ap); + sqlite3_str_vappendf(&acc, zFormat, ap); zBuf[acc.nChar] = 0; return zBuf; } @@ -26586,7 +27778,7 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ ** allocate memory because it might be called while the memory allocator ** mutex is held. ** -** sqlite3VXPrintf() might ask for *temporary* memory allocations for +** sqlite3_str_vappendf() might ask for *temporary* memory allocations for ** certain format characters (%q) or for very large precisions or widths. ** Care must be taken that any sqlite3_log() calls that occur while the ** memory mutex is held do not use these mechanisms. @@ -26596,7 +27788,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); - sqlite3VXPrintf(&acc, zFormat, ap); + sqlite3_str_vappendf(&acc, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); } @@ -26625,23 +27817,30 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ char zBuf[500]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); va_start(ap,zFormat); - sqlite3VXPrintf(&acc, zFormat, ap); + sqlite3_str_vappendf(&acc, zFormat, ap); va_end(ap); sqlite3StrAccumFinish(&acc); +#ifdef SQLITE_OS_TRACE_PROC + { + extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf); + SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf)); + } +#else fprintf(stdout,"%s", zBuf); fflush(stdout); +#endif } #endif /* -** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument +** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. */ -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ +SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ va_list ap; va_start(ap,zFormat); - sqlite3VXPrintf(p, zFormat, ap); + sqlite3_str_vappendf(p, zFormat, ap); va_end(ap); } @@ -26707,15 +27906,17 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); if( p ){ for(i=0; iiLevel && ibLine)-1; i++){ - sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); + sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); } - sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + } + if( zFormat!=0 ){ + va_start(ap, zFormat); + sqlite3_str_vappendf(&acc, zFormat, ap); + va_end(ap); + assert( acc.nChar>0 ); + sqlite3_str_append(&acc, "\n", 1); } - va_start(ap, zFormat); - sqlite3VXPrintf(&acc, zFormat, ap); - va_end(ap); - assert( acc.nChar>0 ); - if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); fflush(stdout); @@ -26748,17 +27949,17 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m char zLine[1000]; const struct Cte *pCte = &pWith->a[i]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, "%s", pCte->zName); + sqlite3_str_appendf(&x, "%s", pCte->zName); if( pCte->pCols && pCte->pCols->nExpr>0 ){ char cSep = '('; int j; for(j=0; jpCols->nExpr; j++){ - sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); + sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); cSep = ','; } - sqlite3XPrintf(&x, ")"); + sqlite3_str_appendf(&x, ")"); } - sqlite3XPrintf(&x, " AS"); + sqlite3_str_appendf(&x, " AS"); sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, inCte-1); sqlite3TreeViewSelect(pView, pCte->pSelect, 0); @@ -26786,11 +27987,21 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m sqlite3TreeViewPush(pView, 1); } do{ +#if SELECTTRACE_ENABLED + sqlite3TreeViewLine(pView, + "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), + p->zSelName, p, p->selFlags, + (int)p->nSelectRow + ); +#else sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, (int)p->nSelectRow ); +#endif if( cnt++ ) sqlite3TreeViewPop(pView); if( p->pPrior ){ n = 1000; @@ -26802,7 +28013,6 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m if( p->pHaving ) n++; if( p->pOrderBy ) n++; if( p->pLimit ) n++; - if( p->pOffset ) n++; } sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); if( p->pSrc && p->pSrc->nSrc ){ @@ -26814,20 +28024,20 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m StrAccum x; char zLine[100]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); + sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); if( pItem->zDatabase ){ - sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); + sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); }else if( pItem->zName ){ - sqlite3XPrintf(&x, " %s", pItem->zName); + sqlite3_str_appendf(&x, " %s", pItem->zName); } if( pItem->pTab ){ - sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); + sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); } if( pItem->zAlias ){ - sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); + sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); } if( pItem->fg.jointype & JT_LEFT ){ - sqlite3XPrintf(&x, " LEFT-JOIN"); + sqlite3_str_appendf(&x, " LEFT-JOIN"); } sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1); @@ -26859,12 +28069,12 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m } if( p->pLimit ){ sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); - sqlite3TreeViewExpr(pView, p->pLimit, 0); - sqlite3TreeViewPop(pView); - } - if( p->pOffset ){ - sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); - sqlite3TreeViewExpr(pView, p->pOffset, 0); + sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); + if( p->pLimit->pRight ){ + sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); + sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); + sqlite3TreeViewPop(pView); + } sqlite3TreeViewPop(pView); } if( p->pPrior ){ @@ -26942,6 +28152,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewLine(pView,"NULL"); break; } + case TK_TRUEFALSE: { + sqlite3TreeViewLine(pView, + sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE"); + break; + } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); @@ -26998,6 +28213,19 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; + case TK_TRUTH: { + int x; + const char *azOp[] = { + "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" + }; + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); + assert( pExpr->pRight ); + assert( pExpr->pRight->op==TK_TRUEFALSE ); + x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); + zUniOp = azOp[x]; + break; + } + case TK_SPAN: { sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); @@ -27157,12 +28385,25 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList( sqlite3TreeViewLine(pView, "%s", zLabel); for(i=0; inExpr; i++){ int j = pList->a[i].u.x.iOrderByCol; - if( j ){ - sqlite3TreeViewPush(pView, 0); - sqlite3TreeViewLine(pView, "iOrderByCol=%d", j); + char *zName = pList->a[i].zName; + int moreToFollow = inExpr - 1; + if( j || zName ){ + sqlite3TreeViewPush(pView, moreToFollow); + moreToFollow = 0; + sqlite3TreeViewLine(pView, 0); + if( zName ){ + fprintf(stdout, "AS %s ", zName); + } + if( j ){ + fprintf(stdout, "iOrderByCol=%d", j); + } + fprintf(stdout, "\n"); + fflush(stdout); + } + sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); + if( j || zName ){ + sqlite3TreeViewPop(pView); } - sqlite3TreeViewExpr(pView, pList->a[i].pExpr, inExpr-1); - if( j ) sqlite3TreeViewPop(pView); } } } @@ -28452,6 +29693,45 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; } +/* +** Compute 10 to the E-th power. Examples: E==1 results in 10. +** E==2 results in 100. E==50 results in 1.0e50. +** +** This routine only works for values of E between 1 and 341. +*/ +static LONGDOUBLE_TYPE sqlite3Pow10(int E){ +#if defined(_MSC_VER) + static const LONGDOUBLE_TYPE x[] = { + 1.0e+001, + 1.0e+002, + 1.0e+004, + 1.0e+008, + 1.0e+016, + 1.0e+032, + 1.0e+064, + 1.0e+128, + 1.0e+256 + }; + LONGDOUBLE_TYPE r = 1.0; + int i; + assert( E>=0 && E<=307 ); + for(i=0; E!=0; i++, E >>=1){ + if( E & 1 ) r *= x[i]; + } + return r; +#else + LONGDOUBLE_TYPE x = 10.0; + LONGDOUBLE_TYPE r = 1.0; + while(1){ + if( E & 1 ) r *= x; + E >>= 1; + if( E==0 ) break; + x *= x; + } + return r; +#endif +} + /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. @@ -28519,12 +29799,12 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en /* copy max significant digits to significand */ while( z=zEnd ) goto do_atof_calc; /* if decimal point is present */ @@ -28537,7 +29817,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en s = s*10 + (*z - '0'); d--; } - z+=incr, nDigits++; + z+=incr; nDigits++; } } if( z>=zEnd ) goto do_atof_calc; @@ -28607,11 +29887,10 @@ do_atof_calc: if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ result = (double)s; }else{ - LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ - while( e%308 ) { scale *= 1.0e+1; e -= 1; } + LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); if( esign<0 ){ result = s / scale; result /= 1.0e+308; @@ -28631,10 +29910,7 @@ do_atof_calc: } } }else{ - /* 1.0e+22 is the largest power of 10 than can be - ** represented exactly. */ - while( e%22 ) { scale *= 1.0e+1; e -= 1; } - while( e>0 ) { scale *= 1.0e+22; e -= 22; } + LONGDOUBLE_TYPE scale = sqlite3Pow10(e); if( esign<0 ){ result = s / scale; }else{ @@ -28692,7 +29968,7 @@ static int compare2pow63(const char *zNum, int incr){ ** Returns: ** ** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Excess text after the integer value +** 1 Excess non-space text after the integer value ** 2 Integer too large for a 64-bit signed integer or is malformed ** 3 Special case of 9223372036854775808 ** @@ -28735,47 +30011,57 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc for(i=0; &zNum[i]='0' && c<='9'; i+=incr){ u = u*10 + c - '0'; } + testcase( i==18*incr ); + testcase( i==19*incr ); + testcase( i==20*incr ); if( u>LARGEST_INT64 ){ + /* This test and assignment is needed only to suppress UB warnings + ** from clang and -fsanitize=undefined. This test and assignment make + ** the code a little larger and slower, and no harm comes from omitting + ** them, but we must appaise the undefined-behavior pharisees. */ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; }else if( neg ){ *pNum = -(i64)u; }else{ *pNum = (i64)u; } - testcase( i==18 ); - testcase( i==19 ); - testcase( i==20 ); - if( &zNum[i]19*incr ){ /* Too many digits */ - /* zNum is empty or contains non-numeric text or is longer - ** than 19 digits (thus guaranteeing that it is too large) */ - return 2; - }else if( i<19*incr ){ + if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ assert( u<=LARGEST_INT64 ); return rc; }else{ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ - c = compare2pow63(zNum, incr); + c = i>19*incr ? 1 : compare2pow63(zNum, incr); if( c<0 ){ /* zNum is less than 9223372036854775808 so it fits */ assert( u<=LARGEST_INT64 ); return rc; - }else if( c>0 ){ - /* zNum is greater than 9223372036854775808 so it overflows */ - return 2; }else{ - /* zNum is exactly 9223372036854775808. Fits if negative. The - ** special case 2 overflow if positive */ - assert( u-1==LARGEST_INT64 ); - return neg ? rc : 3; + *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; + if( c>0 ){ + /* zNum is greater than 9223372036854775808 so it overflows */ + return 2; + }else{ + /* zNum is exactly 9223372036854775808. Fits if negative. The + ** special case 2 overflow if positive */ + assert( u-1==LARGEST_INT64 ); + return neg ? rc : 3; + } } } } @@ -30080,90 +31366,94 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 81 */ "RealAffinity" OpHelp(""), /* 82 */ "Cast" OpHelp("affinity(r[P1])"), /* 83 */ "Permutation" OpHelp(""), - /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 88 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 89 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 90 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), - /* 96 */ "Column" OpHelp("r[P3]=PX"), - /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 100 */ "Count" OpHelp("r[P2]=count()"), - /* 101 */ "ReadCookie" OpHelp(""), - /* 102 */ "SetCookie" OpHelp(""), - /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 106 */ "OpenDup" OpHelp(""), - /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 109 */ "SorterOpen" OpHelp(""), - /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 112 */ "Close" OpHelp(""), - /* 113 */ "ColumnsUsed" OpHelp(""), - /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 118 */ "Delete" OpHelp(""), - /* 119 */ "ResetCount" OpHelp(""), - /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 121 */ "SorterData" OpHelp("r[P2]=data"), - /* 122 */ "RowData" OpHelp("r[P2]=data"), - /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 124 */ "NullRow" OpHelp(""), - /* 125 */ "SeekEnd" OpHelp(""), - /* 126 */ "SorterInsert" OpHelp("key=r[P2]"), - /* 127 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 128 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 129 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), - /* 130 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 131 */ "Destroy" OpHelp(""), - /* 132 */ "Real" OpHelp("r[P2]=P4"), - /* 133 */ "Clear" OpHelp(""), - /* 134 */ "ResetSorter" OpHelp(""), - /* 135 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), - /* 136 */ "SqlExec" OpHelp(""), - /* 137 */ "ParseSchema" OpHelp(""), - /* 138 */ "LoadAnalysis" OpHelp(""), - /* 139 */ "DropTable" OpHelp(""), - /* 140 */ "DropIndex" OpHelp(""), - /* 141 */ "DropTrigger" OpHelp(""), - /* 142 */ "IntegrityCk" OpHelp(""), - /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 144 */ "Param" OpHelp(""), - /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 151 */ "Expire" OpHelp(""), - /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 153 */ "VBegin" OpHelp(""), - /* 154 */ "VCreate" OpHelp(""), - /* 155 */ "VDestroy" OpHelp(""), - /* 156 */ "VOpen" OpHelp(""), - /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 158 */ "VRename" OpHelp(""), - /* 159 */ "Pagecount" OpHelp(""), - /* 160 */ "MaxPgcnt" OpHelp(""), - /* 161 */ "PureFunc0" OpHelp(""), - /* 162 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 163 */ "PureFunc" OpHelp(""), - /* 164 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 165 */ "CursorHint" OpHelp(""), - /* 166 */ "Noop" OpHelp(""), - /* 167 */ "Explain" OpHelp(""), + /* 84 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), + /* 95 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), + /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 97 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), + /* 98 */ "Column" OpHelp("r[P3]=PX"), + /* 99 */ "String8" OpHelp("r[P2]='P4'"), + /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 102 */ "Count" OpHelp("r[P2]=count()"), + /* 103 */ "ReadCookie" OpHelp(""), + /* 104 */ "SetCookie" OpHelp(""), + /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 108 */ "OpenDup" OpHelp(""), + /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 111 */ "SorterOpen" OpHelp(""), + /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 114 */ "Close" OpHelp(""), + /* 115 */ "ColumnsUsed" OpHelp(""), + /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 120 */ "Delete" OpHelp(""), + /* 121 */ "ResetCount" OpHelp(""), + /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 123 */ "SorterData" OpHelp("r[P2]=data"), + /* 124 */ "RowData" OpHelp("r[P2]=data"), + /* 125 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 126 */ "NullRow" OpHelp(""), + /* 127 */ "SeekEnd" OpHelp(""), + /* 128 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 129 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 130 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 131 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), + /* 132 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 133 */ "Destroy" OpHelp(""), + /* 134 */ "Real" OpHelp("r[P2]=P4"), + /* 135 */ "Clear" OpHelp(""), + /* 136 */ "ResetSorter" OpHelp(""), + /* 137 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), + /* 138 */ "SqlExec" OpHelp(""), + /* 139 */ "ParseSchema" OpHelp(""), + /* 140 */ "LoadAnalysis" OpHelp(""), + /* 141 */ "DropTable" OpHelp(""), + /* 142 */ "DropIndex" OpHelp(""), + /* 143 */ "DropTrigger" OpHelp(""), + /* 144 */ "IntegrityCk" OpHelp(""), + /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 146 */ "Param" OpHelp(""), + /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 153 */ "Expire" OpHelp(""), + /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 155 */ "VBegin" OpHelp(""), + /* 156 */ "VCreate" OpHelp(""), + /* 157 */ "VDestroy" OpHelp(""), + /* 158 */ "VOpen" OpHelp(""), + /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 160 */ "VRename" OpHelp(""), + /* 161 */ "Pagecount" OpHelp(""), + /* 162 */ "MaxPgcnt" OpHelp(""), + /* 163 */ "PureFunc0" OpHelp(""), + /* 164 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 165 */ "PureFunc" OpHelp(""), + /* 166 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 167 */ "Trace" OpHelp(""), + /* 168 */ "CursorHint" OpHelp(""), + /* 169 */ "Noop" OpHelp(""), + /* 170 */ "Explain" OpHelp(""), + /* 171 */ "Abortable" OpHelp(""), }; return azName[i]; } @@ -30402,6 +31692,9 @@ struct unixFile { #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + unsigned iBusyTimeout; /* Wait this many millisec on locks */ +#endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif @@ -30839,7 +32132,11 @@ static struct unix_syscall { #endif #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) +#if defined(HAVE_FCHOWN) { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, +#else + { "geteuid", (sqlite3_syscall_ptr)0, 0 }, +#endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 @@ -30854,7 +32151,7 @@ static struct unix_syscall { #else { "munmap", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) +#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, @@ -30884,7 +32181,11 @@ static struct unix_syscall { #endif #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, +#else + { "ioctl", (sqlite3_syscall_ptr)0, 0 }, +#endif #define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) }; /* End of the overrideable system calls */ @@ -31063,15 +32364,16 @@ static int robust_open(const char *z, int f, mode_t m){ ** assert( unixMutexHeld() ); ** unixEnterLeave() */ +static sqlite3_mutex *unixBigLock = 0; static void unixEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(unixBigLock); } static void unixLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(unixBigLock); } #ifdef SQLITE_DEBUG static int unixMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(unixBigLock); } #endif @@ -31827,6 +33129,43 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ return rc; } +/* +** Set a posix-advisory-lock. +** +** There are two versions of this routine. If compiled with +** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter +** which is a pointer to a unixFile. If the unixFile->iBusyTimeout +** value is set, then it is the number of milliseconds to wait before +** failing the lock. The iBusyTimeout value is always reset back to +** zero on each call. +** +** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking +** attempt to set the lock. +*/ +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT +# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) +#else +static int osSetPosixAdvisoryLock( + int h, /* The file descriptor on which to take the lock */ + struct flock *pLock, /* The description of the lock */ + unixFile *pFile /* Structure holding timeout value */ +){ + int rc = osFcntl(h,F_SETLK,pLock); + while( rc<0 && pFile->iBusyTimeout>0 ){ + /* On systems that support some kind of blocking file lock with a timeout, + ** make appropriate changes here to invoke that blocking file lock. On + ** generic posix, however, there is no such API. So we simply try the + ** lock once every millisecond until either the timeout expires, or until + ** the lock is obtained. */ + usleep(1000); + rc = osFcntl(h,F_SETLK,pLock); + pFile->iBusyTimeout--; + } + return rc; +} +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ + + /* ** Attempt to set a system-lock on the file pFile. The lock is ** described by pLock. @@ -31859,7 +33198,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; - rc = osFcntl(pFile->h, F_SETLK, &lock); + rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); if( rc<0 ) return rc; pInode->bProcessLock = 1; pInode->nLock++; @@ -31867,7 +33206,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ rc = 0; } }else{ - rc = osFcntl(pFile->h, F_SETLK, pLock); + rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); } return rc; } @@ -34101,7 +35440,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ do{ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); }while( err==EINTR ); - if( err ) return SQLITE_IOERR_WRITE; + if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; #else /* If the OS does not have posix_fallocate(), fake it. Write a ** single byte to the last byte in each block that falls entirely @@ -34227,6 +35566,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ *(int*)pArg = fileHasMoved(pFile); return SQLITE_OK; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + case SQLITE_FCNTL_LOCK_TIMEOUT: { + pFile->iBusyTimeout = *(int*)pArg; + return SQLITE_OK; + } +#endif #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; @@ -34317,7 +35662,7 @@ static void setDeviceCharacteristics(unixFile *pFile){ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; pFile->deviceCharacteristics = 0; if( fstatvfs(pFile->h, &fsInfo) == -1 ) { - return pFile->sectorSize; + return; } if( !strcmp(fsInfo.f_basetype, "tmp") ) { @@ -34475,6 +35820,7 @@ struct unixShmNode { int szRegion; /* Size of shared-memory regions */ u16 nRegion; /* Size of array apRegion */ u8 isReadonly; /* True if read-only */ + u8 isUnlocked; /* True if no DMS lock held */ char **apRegion; /* Array of mapped shared-memory regions */ int nRef; /* Number of unixShm objects pointing to this */ unixShm *pFirst; /* All unixShm objects pointing to this */ @@ -34531,7 +35877,7 @@ static int unixShmSystemLock( /* Access to the unixShmNode object is serialized by the caller */ pShmNode = pFile->pInode->pShmNode; - assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); + assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) ); /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); @@ -34541,13 +35887,11 @@ static int unixShmSystemLock( if( pShmNode->h>=0 ){ /* Initialize the locking parameters */ - memset(&f, 0, sizeof(f)); f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - - rc = osFcntl(pShmNode->h, F_SETLK, &f); + rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; } @@ -34637,6 +35981,64 @@ static void unixShmPurge(unixFile *pFd){ } } +/* +** The DMS lock has not yet been taken on shm file pShmNode. Attempt to +** take it now. Return SQLITE_OK if successful, or an SQLite error +** code otherwise. +** +** If the DMS cannot be locked because this is a readonly_shm=1 +** connection and no other process already holds a lock, return +** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. +*/ +static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ + struct flock lock; + int rc = SQLITE_OK; + + /* Use F_GETLK to determine the locks other processes are holding + ** on the DMS byte. If it indicates that another process is holding + ** a SHARED lock, then this process may also take a SHARED lock + ** and proceed with opening the *-shm file. + ** + ** Or, if no other process is holding any lock, then this process + ** is the first to open it. In this case take an EXCLUSIVE lock on the + ** DMS byte and truncate the *-shm file to zero bytes in size. Then + ** downgrade to a SHARED lock on the DMS byte. + ** + ** If another process is holding an EXCLUSIVE lock on the DMS byte, + ** return SQLITE_BUSY to the caller (it will try again). An earlier + ** version of this code attempted the SHARED lock at this point. But + ** this introduced a subtle race condition: if the process holding + ** EXCLUSIVE failed just before truncating the *-shm file, then this + ** process might open and use the *-shm file without truncating it. + ** And if the *-shm file has been corrupted by a power failure or + ** system crash, the database itself may also become corrupt. */ + lock.l_whence = SEEK_SET; + lock.l_start = UNIX_SHM_DMS; + lock.l_len = 1; + lock.l_type = F_WRLCK; + if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) { + rc = SQLITE_IOERR_LOCK; + }else if( lock.l_type==F_UNLCK ){ + if( pShmNode->isReadonly ){ + pShmNode->isUnlocked = 1; + rc = SQLITE_READONLY_CANTINIT; + }else{ + rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); + if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){ + rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); + } + } + }else if( lock.l_type==F_WRLCK ){ + rc = SQLITE_BUSY; + } + + if( rc==SQLITE_OK ){ + assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); + rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); + } + return rc; +} + /* ** Open a shared-memory area associated with open database file pDbFd. ** This particular implementation uses mmapped files. @@ -34675,9 +36077,9 @@ static void unixShmPurge(unixFile *pFd){ static int unixOpenSharedMemory(unixFile *pDbFd){ struct unixShm *p = 0; /* The connection to be opened */ struct unixShmNode *pShmNode; /* The underlying mmapped file */ - int rc; /* Result code */ + int rc = SQLITE_OK; /* Result code */ unixInodeInfo *pInode; /* The inode of fd */ - char *zShmFilename; /* Name of the file used for SHM */ + char *zShm; /* Name of the file used for SHM */ int nShmFilename; /* Size of the SHM filename in bytes */ /* Allocate space for the new unixShm object. */ @@ -34718,14 +36120,14 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ goto shm_open_err; } memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); - zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1]; + zShm = pShmNode->zFilename = (char*)&pShmNode[1]; #ifdef SQLITE_SHM_DIRECTORY - sqlite3_snprintf(nShmFilename, zShmFilename, + sqlite3_snprintf(nShmFilename, zShm, SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", (u32)sStat.st_ino, (u32)sStat.st_dev); #else - sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); - sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); + sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); + sqlite3FileSuffix3(pDbFd->zPath, zShm); #endif pShmNode->h = -1; pDbFd->pInode->pShmNode = pShmNode; @@ -34739,15 +36141,16 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ } if( pInode->bProcessLock==0 ){ - int openFlags = O_RDWR | O_CREAT; - if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - openFlags = O_RDONLY; - pShmNode->isReadonly = 1; + if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ + pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777)); } - pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777)); if( pShmNode->h<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename); - goto shm_open_err; + pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); + if( pShmNode->h<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); + goto shm_open_err; + } + pShmNode->isReadonly = 1; } /* If this process is running as root, make sure that the SHM file @@ -34755,20 +36158,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ ** the original owner will not be able to connect. */ robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); - - /* Check to see if another process is holding the dead-man switch. - ** If not, truncate the file to zero length. - */ - rc = SQLITE_OK; - if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ - if( robust_ftruncate(pShmNode->h, 0) ){ - rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); - } - } - if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); - } - if( rc ) goto shm_open_err; + + rc = unixLockSharedMemory(pDbFd, pShmNode); + if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; } } @@ -34792,7 +36184,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; sqlite3_mutex_leave(pShmNode->mutex); - return SQLITE_OK; + return rc; /* Jump here on any error */ shm_open_err: @@ -34844,6 +36236,11 @@ static int unixShmMap( p = pDbFd->pShm; pShmNode = p->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); + if( pShmNode->isUnlocked ){ + rc = unixLockSharedMemory(pDbFd, pShmNode); + if( rc!=SQLITE_OK ) goto shmpage_out; + pShmNode->isUnlocked = 0; + } assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); assert( pShmNode->pInode==pDbFd->pInode ); assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); @@ -36112,7 +37509,7 @@ static int unixOpen( ** a file-descriptor on the directory too. The first time unixSync() ** is called the directory file descriptor will be fsync()ed and close()d. */ - int syncDir = (isCreate && ( + int isNewJrnl = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL @@ -36159,7 +37556,6 @@ static int unixOpen( randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } - memset(p, 0, sizeof(unixFile)); if( eType==SQLITE_OPEN_MAIN_DB ){ @@ -36182,7 +37578,7 @@ static int unixOpen( }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ - assert(isDelete && !syncDir); + assert(isDelete && !isNewJrnl); rc = unixGetTempname(pVfs->mxPathname, zTmpname); if( rc!=SQLITE_OK ){ return rc; @@ -36217,17 +37613,24 @@ static int unixOpen( fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); assert( !isExclusive || (openFlags & O_CREAT)!=0 ); - if( fd<0 && errno!=EISDIR && isReadWrite ){ - /* Failed to open the file for read/write access. Try read-only. */ - flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); - openFlags &= ~(O_RDWR|O_CREAT); - flags |= SQLITE_OPEN_READONLY; - openFlags |= O_RDONLY; - isReadonly = 1; - fd = robust_open(zName, openFlags, openMode); + if( fd<0 ){ + if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ + /* If unable to create a journal because the directory is not + ** writable, change the error code to indicate that. */ + rc = SQLITE_READONLY_DIRECTORY; + }else if( errno!=EISDIR && isReadWrite ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + openFlags &= ~(O_RDWR|O_CREAT); + flags |= SQLITE_OPEN_READONLY; + openFlags |= O_RDONLY; + isReadonly = 1; + fd = robust_open(zName, openFlags, openMode); + } } if( fd<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); + int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); + if( rc==SQLITE_OK ) rc = rc2; goto open_finished; } @@ -36287,7 +37690,7 @@ static int unixOpen( if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; - if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; + if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; #if SQLITE_ENABLE_LOCKING_STYLE @@ -38027,6 +39430,7 @@ SQLITE_API int sqlite3_os_init(void){ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } + unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); return SQLITE_OK; } @@ -38038,6 +39442,7 @@ SQLITE_API int sqlite3_os_init(void){ ** This routine is a no-op for unix. */ SQLITE_API int sqlite3_os_end(void){ + unixBigLock = 0; return SQLITE_OK; } @@ -38560,22 +39965,6 @@ struct winVfsAppData { # define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) #endif -/* - * The value used with sqlite3_win32_set_directory() to specify that - * the data directory should be changed. - */ -#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE -# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) -#endif - -/* - * The value used with sqlite3_win32_set_directory() to specify that - * the temporary directory should be changed. - */ -#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE -# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) -#endif - /* * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the * various Win32 API heap functions instead of our own. @@ -40172,13 +41561,13 @@ SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ } /* -** This function sets the data directory or the temporary directory based on -** the provided arguments. The type argument must be 1 in order to set the -** data directory or 2 in order to set the temporary directory. The zValue -** argument is the name of the directory to use. The return value will be -** SQLITE_OK if successful. +** This function is the same as sqlite3_win32_set_directory (below); however, +** it accepts a UTF-8 string. */ -SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +SQLITE_API int sqlite3_win32_set_directory8( + unsigned long type, /* Identifier for directory being set or reset */ + const char *zValue /* New value for directory being set or reset */ +){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -40194,20 +41583,53 @@ SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ ); assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); if( ppDirectory ){ - char *zValueUtf8 = 0; + char *zCopy = 0; if( zValue && zValue[0] ){ - zValueUtf8 = winUnicodeToUtf8(zValue); - if ( zValueUtf8==0 ){ + zCopy = sqlite3_mprintf("%s", zValue); + if ( zCopy==0 ){ return SQLITE_NOMEM_BKPT; } } sqlite3_free(*ppDirectory); - *ppDirectory = zValueUtf8; + *ppDirectory = zCopy; return SQLITE_OK; } return SQLITE_ERROR; } +/* +** This function is the same as sqlite3_win32_set_directory (below); however, +** it accepts a UTF-16 string. +*/ +SQLITE_API int sqlite3_win32_set_directory16( + unsigned long type, /* Identifier for directory being set or reset */ + const void *zValue /* New value for directory being set or reset */ +){ + int rc; + char *zUtf8 = 0; + if( zValue ){ + zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); + if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; + } + rc = sqlite3_win32_set_directory8(type, zUtf8); + if( zUtf8 ) sqlite3_free(zUtf8); + return rc; +} + +/* +** This function sets the data directory or the temporary directory based on +** the provided arguments. The type argument must be 1 in order to set the +** data directory or 2 in order to set the temporary directory. The zValue +** argument is the name of the directory to use. The return value will be +** SQLITE_OK if successful. +*/ +SQLITE_API int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +){ + return sqlite3_win32_set_directory16(type, zValue); +} + /* ** The return value of winGetLastErrorMsg ** is zero if the error message fits in the buffer, or non-zero @@ -41876,15 +43298,16 @@ static SYSTEM_INFO winSysInfo; ** assert( winShmMutexHeld() ); ** winShmLeaveMutex() */ +static sqlite3_mutex *winBigLock = 0; static void winShmEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(winBigLock); } static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(winBigLock); } #ifndef NDEBUG static int winShmMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(winBigLock); } #endif @@ -41918,6 +43341,9 @@ struct winShmNode { int szRegion; /* Size of shared-memory regions */ int nRegion; /* Size of array apRegion */ + u8 isReadonly; /* True if read-only */ + u8 isUnlocked; /* True if no DMS lock held */ + struct ShmRegion { HANDLE hMap; /* File handle from CreateFileMapping */ void *pMap; @@ -41984,7 +43410,7 @@ static int winShmSystemLock( int rc = 0; /* Result code form Lock/UnlockFileEx() */ /* Access to the winShmNode object is serialized by the caller */ - assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); + assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) ); OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", pFile->hFile.h, lockType, ofst, nByte)); @@ -42065,6 +43491,37 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ } } +/* +** The DMS lock has not yet been taken on shm file pShmNode. Attempt to +** take it now. Return SQLITE_OK if successful, or an SQLite error +** code otherwise. +** +** If the DMS cannot be locked because this is a readonly_shm=1 +** connection and no other process already holds a lock, return +** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. +*/ +static int winLockSharedMemory(winShmNode *pShmNode){ + int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1); + + if( rc==SQLITE_OK ){ + if( pShmNode->isReadonly ){ + pShmNode->isUnlocked = 1; + winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); + return SQLITE_READONLY_CANTINIT; + }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){ + winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); + return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), + "winLockSharedMemory", pShmNode->zFilename); + } + } + + if( rc==SQLITE_OK ){ + winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); + } + + return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); +} + /* ** Open the shared-memory area associated with database file pDbFd. ** @@ -42074,9 +43531,9 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ */ static int winOpenSharedMemory(winFile *pDbFd){ struct winShm *p; /* The connection to be opened */ - struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ - int rc; /* Result code */ - struct winShmNode *pNew; /* Newly allocated winShmNode */ + winShmNode *pShmNode = 0; /* The underlying mmapped file */ + int rc = SQLITE_OK; /* Result code */ + winShmNode *pNew; /* Newly allocated winShmNode */ int nName; /* Size of zName in bytes */ assert( pDbFd->pShm==0 ); /* Not previously opened */ @@ -42109,6 +43566,9 @@ static int winOpenSharedMemory(winFile *pDbFd){ if( pShmNode ){ sqlite3_free(pNew); }else{ + int inFlags = SQLITE_OPEN_WAL; + int outFlags = 0; + pShmNode = pNew; pNew = 0; ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; @@ -42123,30 +43583,23 @@ static int winOpenSharedMemory(winFile *pDbFd){ } } - rc = winOpen(pDbFd->pVfs, - pShmNode->zFilename, /* Name of the file (UTF-8) */ - (sqlite3_file*)&pShmNode->hFile, /* File handle here */ - SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, - 0); - if( SQLITE_OK!=rc ){ + if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ + inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + }else{ + inFlags |= SQLITE_OPEN_READONLY; + } + rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, + (sqlite3_file*)&pShmNode->hFile, + inFlags, &outFlags); + if( rc!=SQLITE_OK ){ + rc = winLogError(rc, osGetLastError(), "winOpenShm", + pShmNode->zFilename); goto shm_open_err; } + if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1; - /* Check to see if another process is holding the dead-man switch. - ** If not, truncate the file to zero length. - */ - if( winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ - rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); - if( rc!=SQLITE_OK ){ - rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), - "winOpenShm", pDbFd->zPath); - } - } - if( rc==SQLITE_OK ){ - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); - rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); - } - if( rc ) goto shm_open_err; + rc = winLockSharedMemory(pShmNode); + if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; } /* Make the new connection a child of the winShmNode */ @@ -42169,7 +43622,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; sqlite3_mutex_leave(pShmNode->mutex); - return SQLITE_OK; + return rc; /* Jump here on any error */ shm_open_err: @@ -42373,6 +43826,8 @@ static int winShmMap( winFile *pDbFd = (winFile*)fd; winShm *pShm = pDbFd->pShm; winShmNode *pShmNode; + DWORD protect = PAGE_READWRITE; + DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ; int rc = SQLITE_OK; if( !pShm ){ @@ -42383,6 +43838,11 @@ static int winShmMap( pShmNode = pShm->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); + if( pShmNode->isUnlocked ){ + rc = winLockSharedMemory(pShmNode); + if( rc!=SQLITE_OK ) goto shmpage_out; + pShmNode->isUnlocked = 0; + } assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); if( pShmNode->nRegion<=iRegion ){ @@ -42429,21 +43889,26 @@ static int winShmMap( } pShmNode->aRegion = apNew; + if( pShmNode->isReadonly ){ + protect = PAGE_READONLY; + flags = FILE_MAP_READ; + } + while( pShmNode->nRegion<=iRegion ){ HANDLE hMap = NULL; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ #if SQLITE_OS_WINRT hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, - NULL, PAGE_READWRITE, nByte, NULL + NULL, protect, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_WIDE) hMap = osCreateFileMappingW(pShmNode->hFile.h, - NULL, PAGE_READWRITE, 0, nByte, NULL + NULL, protect, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(pShmNode->hFile.h, - NULL, PAGE_READWRITE, 0, nByte, NULL + NULL, protect, 0, nByte, NULL ); #endif OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", @@ -42453,11 +43918,11 @@ static int winShmMap( int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; #if SQLITE_OS_WINRT - pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, + pMap = osMapViewOfFileFromApp(hMap, flags, iOffset - iOffsetShift, szRegion + iOffsetShift ); #else - pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, + pMap = osMapViewOfFile(hMap, flags, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); #endif @@ -42488,6 +43953,7 @@ shmpage_out: }else{ *pp = 0; } + if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; sqlite3_mutex_leave(pShmNode->mutex); return rc; } @@ -43316,8 +44782,10 @@ static int winOpen( &extendedParameters); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ - int isRO = 0; - int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); + rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); @@ -43331,8 +44799,10 @@ static int winOpen( NULL); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ - int isRO = 0; - int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); + rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); @@ -43349,8 +44819,10 @@ static int winOpen( NULL); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ - int isRO = 0; - int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); + rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); @@ -44258,6 +45730,10 @@ SQLITE_API int sqlite3_os_init(void){ sqlite3_vfs_register(&winLongPathNolockVfs, 0); #endif +#ifndef SQLITE_OMIT_WAL + winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); +#endif + return SQLITE_OK; } @@ -44268,12 +45744,609 @@ SQLITE_API int sqlite3_os_end(void){ sleepObj = NULL; } #endif + +#ifndef SQLITE_OMIT_WAL + winBigLock = 0; +#endif + return SQLITE_OK; } #endif /* SQLITE_OS_WIN */ /************** End of os_win.c **********************************************/ +/************** Begin file memdb.c *******************************************/ +/* +** 2016-09-07 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file implements an in-memory VFS. A database is held as a contiguous +** block of memory. +** +** This file also implements interface sqlite3_serialize() and +** sqlite3_deserialize(). +*/ +#ifdef SQLITE_ENABLE_DESERIALIZE +/* #include "sqliteInt.h" */ + +/* +** Forward declaration of objects used by this utility +*/ +typedef struct sqlite3_vfs MemVfs; +typedef struct MemFile MemFile; + +/* Access to a lower-level VFS that (might) implement dynamic loading, +** access to randomness, etc. +*/ +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) + +/* An open file */ +struct MemFile { + sqlite3_file base; /* IO methods */ + sqlite3_int64 sz; /* Size of the file */ + sqlite3_int64 szMax; /* Space allocated to aData */ + unsigned char *aData; /* content of the file */ + int nMmap; /* Number of memory mapped pages */ + unsigned mFlags; /* Flags */ + int eLock; /* Most recent lock against this file */ +}; + +/* +** Methods for MemFile +*/ +static int memdbClose(sqlite3_file*); +static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); +static int memdbSync(sqlite3_file*, int flags); +static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int memdbLock(sqlite3_file*, int); +/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ +static int memdbFileControl(sqlite3_file*, int op, void *pArg); +/* static int memdbSectorSize(sqlite3_file*); // not used */ +static int memdbDeviceCharacteristics(sqlite3_file*); +static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); +static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); + +/* +** Methods for MemVfs +*/ +static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ +static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); +static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); +static void memdbDlClose(sqlite3_vfs*, void*); +static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int memdbSleep(sqlite3_vfs*, int microseconds); +/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ +static int memdbGetLastError(sqlite3_vfs*, int, char *); +static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); + +static sqlite3_vfs memdb_vfs = { + 2, /* iVersion */ + 0, /* szOsFile (set when registered) */ + 1024, /* mxPathname */ + 0, /* pNext */ + "memdb", /* zName */ + 0, /* pAppData (set when registered) */ + memdbOpen, /* xOpen */ + 0, /* memdbDelete, */ /* xDelete */ + memdbAccess, /* xAccess */ + memdbFullPathname, /* xFullPathname */ + memdbDlOpen, /* xDlOpen */ + memdbDlError, /* xDlError */ + memdbDlSym, /* xDlSym */ + memdbDlClose, /* xDlClose */ + memdbRandomness, /* xRandomness */ + memdbSleep, /* xSleep */ + 0, /* memdbCurrentTime, */ /* xCurrentTime */ + memdbGetLastError, /* xGetLastError */ + memdbCurrentTimeInt64 /* xCurrentTimeInt64 */ +}; + +static const sqlite3_io_methods memdb_io_methods = { + 3, /* iVersion */ + memdbClose, /* xClose */ + memdbRead, /* xRead */ + memdbWrite, /* xWrite */ + memdbTruncate, /* xTruncate */ + memdbSync, /* xSync */ + memdbFileSize, /* xFileSize */ + memdbLock, /* xLock */ + memdbLock, /* xUnlock - same as xLock in this case */ + 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ + memdbFileControl, /* xFileControl */ + 0, /* memdbSectorSize,*/ /* xSectorSize */ + memdbDeviceCharacteristics, /* xDeviceCharacteristics */ + 0, /* xShmMap */ + 0, /* xShmLock */ + 0, /* xShmBarrier */ + 0, /* xShmUnmap */ + memdbFetch, /* xFetch */ + memdbUnfetch /* xUnfetch */ +}; + + + +/* +** Close an memdb-file. +** +** The pData pointer is owned by the application, so there is nothing +** to free. +*/ +static int memdbClose(sqlite3_file *pFile){ + MemFile *p = (MemFile *)pFile; + if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData); + return SQLITE_OK; +} + +/* +** Read data from an memdb-file. +*/ +static int memdbRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + memset(zBuf, 0, iAmt); + if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); + return SQLITE_IOERR_SHORT_READ; + } + memcpy(zBuf, p->aData+iOfst, iAmt); + return SQLITE_OK; +} + +/* +** Try to enlarge the memory allocation to hold at least sz bytes +*/ +static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ + unsigned char *pNew; + if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){ + return SQLITE_FULL; + } + pNew = sqlite3_realloc64(p->aData, newSz); + if( pNew==0 ) return SQLITE_NOMEM; + p->aData = pNew; + p->szMax = newSz; + return SQLITE_OK; +} + +/* +** Write data to an memdb-file. +*/ +static int memdbWrite( + sqlite3_file *pFile, + const void *z, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + int rc; + if( iOfst+iAmt>p->szMax + && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK + ){ + return rc; + } + if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); + p->sz = iOfst+iAmt; + } + memcpy(p->aData+iOfst, z, iAmt); + return SQLITE_OK; +} + +/* +** Truncate an memdb-file. +** +** In rollback mode (which is always the case for memdb, as it does not +** support WAL mode) the truncate() method is only used to reduce +** the size of a file, never to increase the size. +*/ +static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ + MemFile *p = (MemFile *)pFile; + if( NEVER(size>p->sz) ) return SQLITE_FULL; + p->sz = size; + return SQLITE_OK; +} + +/* +** Sync an memdb-file. +*/ +static int memdbSync(sqlite3_file *pFile, int flags){ + return SQLITE_OK; +} + +/* +** Return the current file-size of an memdb-file. +*/ +static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + MemFile *p = (MemFile *)pFile; + *pSize = p->sz; + return SQLITE_OK; +} + +/* +** Lock an memdb-file. +*/ +static int memdbLock(sqlite3_file *pFile, int eLock){ + MemFile *p = (MemFile *)pFile; + p->eLock = eLock; + return SQLITE_OK; +} + +#if 0 /* Never used because memdbAccess() always returns false */ +/* +** Check if another file-handle holds a RESERVED lock on an memdb-file. +*/ +static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + *pResOut = 0; + return SQLITE_OK; +} +#endif + +/* +** File control method. For custom operations on an memdb-file. +*/ +static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ + MemFile *p = (MemFile *)pFile; + int rc = SQLITE_NOTFOUND; + if( op==SQLITE_FCNTL_VFSNAME ){ + *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); + rc = SQLITE_OK; + } + return rc; +} + +#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ +/* +** Return the sector-size in bytes for an memdb-file. +*/ +static int memdbSectorSize(sqlite3_file *pFile){ + return 1024; +} +#endif + +/* +** Return the device characteristic flags supported by an memdb-file. +*/ +static int memdbDeviceCharacteristics(sqlite3_file *pFile){ + return SQLITE_IOCAP_ATOMIC | + SQLITE_IOCAP_POWERSAFE_OVERWRITE | + SQLITE_IOCAP_SAFE_APPEND | + SQLITE_IOCAP_SEQUENTIAL; +} + +/* Fetch a page of a memory-mapped file */ +static int memdbFetch( + sqlite3_file *pFile, + sqlite3_int64 iOfst, + int iAmt, + void **pp +){ + MemFile *p = (MemFile *)pFile; + p->nMmap++; + *pp = (void*)(p->aData + iOfst); + return SQLITE_OK; +} + +/* Release a memory-mapped page */ +static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ + MemFile *p = (MemFile *)pFile; + p->nMmap--; + return SQLITE_OK; +} + +/* +** Open an mem file handle. +*/ +static int memdbOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + MemFile *p = (MemFile*)pFile; + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ + return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags); + } + memset(p, 0, sizeof(*p)); + p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; + assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */ + *pOutFlags = flags | SQLITE_OPEN_MEMORY; + p->base.pMethods = &memdb_io_methods; + return SQLITE_OK; +} + +#if 0 /* Only used to delete rollback journals, master journals, and WAL + ** files, none of which exist in memdb. So this routine is never used */ +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return SQLITE_IOERR_DELETE; +} +#endif + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +** +** With memdb, no files ever exist on disk. So always return false. +*/ +static int memdbAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int memdbFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + return SQLITE_OK; +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ + return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ + ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ + return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); +} + +#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); +} +#endif + +static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ + return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); +} +static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ + return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); +} + +/* +** Translate a database connection pointer and schema name into a +** MemFile pointer. +*/ +static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ + MemFile *p = 0; + int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); + if( rc ) return 0; + if( p->base.pMethods!=&memdb_io_methods ) return 0; + return p; +} + +/* +** Return the serialization of a database +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which database within the connection */ + sqlite3_int64 *piSize, /* Write size here, if not NULL */ + unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ +){ + MemFile *p; + int iDb; + Btree *pBt; + sqlite3_int64 sz; + int szPage = 0; + sqlite3_stmt *pStmt = 0; + unsigned char *pOut; + char *zSql; + int rc; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + p = memdbFromDbSchema(db, zSchema); + iDb = sqlite3FindDbName(db, zSchema); + if( piSize ) *piSize = -1; + if( iDb<0 ) return 0; + if( p ){ + if( piSize ) *piSize = p->sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = p->aData; + }else{ + pOut = sqlite3_malloc64( p->sz ); + if( pOut ) memcpy(pOut, p->aData, p->sz); + } + return pOut; + } + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) return 0; + szPage = sqlite3BtreeGetPageSize(pBt); + zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); + rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; + sqlite3_free(zSql); + if( rc ) return 0; + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_ROW ){ + pOut = 0; + }else{ + sz = sqlite3_column_int64(pStmt, 0)*szPage; + if( piSize ) *piSize = sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = 0; + }else{ + pOut = sqlite3_malloc64( sz ); + if( pOut ){ + int nPage = sqlite3_column_int(pStmt, 0); + Pager *pPager = sqlite3BtreePager(pBt); + int pgno; + for(pgno=1; pgno<=nPage; pgno++){ + DbPage *pPage = 0; + unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); + rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); + if( rc==SQLITE_OK ){ + memcpy(pTo, sqlite3PagerGetData(pPage), szPage); + }else{ + memset(pTo, 0, szPage); + } + sqlite3PagerUnref(pPage); + } + } + } + } + sqlite3_finalize(pStmt); + return pOut; +} + +/* Convert zSchema to a MemDB and initialize its content. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +){ + MemFile *p; + char *zSql; + sqlite3_stmt *pStmt = 0; + int rc; + int iDb; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } + if( szDb<0 ) return SQLITE_MISUSE_BKPT; + if( szBuf<0 ) return SQLITE_MISUSE_BKPT; +#endif + + sqlite3_mutex_enter(db->mutex); + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + iDb = sqlite3FindDbName(db, zSchema); + if( iDb<0 ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ) goto end_deserialize; + db->init.iDb = (u8)iDb; + db->init.reopenMemdb = 1; + rc = sqlite3_step(pStmt); + db->init.reopenMemdb = 0; + if( rc!=SQLITE_DONE ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + p = memdbFromDbSchema(db, zSchema); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + p->aData = pData; + p->sz = szDb; + p->szMax = szBuf; + p->mFlags = mFlags; + rc = SQLITE_OK; + } + +end_deserialize: + sqlite3_finalize(pStmt); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** This routine is called when the extension is loaded. +** Register the new VFS. +*/ +SQLITE_PRIVATE int sqlite3MemdbInit(void){ + sqlite3_vfs *pLower = sqlite3_vfs_find(0); + int sz = pLower->szOsFile; + memdb_vfs.pAppData = pLower; + /* In all known configurations of SQLite, the size of a default + ** sqlite3_file is greater than the size of a memdb sqlite3_file. + ** Should that ever change, remove the following NEVER() */ + if( NEVER(szpgno, pgno, - sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), + sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache), numberOfCachePages(pCache)); #endif pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); @@ -45257,16 +47330,15 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ assert( sqlite3PcachePageSanity(p) ); - if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){ - assert( (p->flags & PGHDR_CLEAN)==0 ); - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); - p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); - p->flags |= PGHDR_CLEAN; - pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); - assert( sqlite3PcachePageSanity(p) ); - if( p->nRef==0 ){ - pcacheUnpin(p); - } + assert( (p->flags & PGHDR_DIRTY)!=0 ); + assert( (p->flags & PGHDR_CLEAN)==0 ); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); + p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); + p->flags |= PGHDR_CLEAN; + pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); + assert( sqlite3PcachePageSanity(p) ); + if( p->nRef==0 ){ + pcacheUnpin(p); } } @@ -48179,7 +50251,7 @@ struct Pager { char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int aStat[3]; /* Total cache hits, misses and writes */ + int aStat[4]; /* Total cache hits, misses, writes, spills */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif @@ -48207,6 +50279,7 @@ struct Pager { #define PAGER_STAT_HIT 0 #define PAGER_STAT_MISS 1 #define PAGER_STAT_WRITE 2 +#define PAGER_STAT_SPILL 3 /* ** The following global variables hold counters used for @@ -48693,7 +50766,7 @@ static int jrnlBufferSize(Pager *pPager){ #endif #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){ + if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){ return -1; } #endif @@ -49609,7 +51682,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ rc = pager_truncate(pPager, pPager->dbSize); } - if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ + if( rc==SQLITE_OK && bCommit ){ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; } @@ -50428,9 +52501,7 @@ end_playback: ** assertion that the transaction counter was modified. */ #ifdef SQLITE_DEBUG - if( pPager->fd->pMethods ){ - sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); - } + sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); #endif /* If this playback is happening automatically as a result of an IO or @@ -51183,20 +53254,18 @@ static int pagerOpentemp( ** retried. If it returns zero, then the SQLITE_BUSY error is ** returned to the caller of the pager API function. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( Pager *pPager, /* Pager object */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ){ + void **ap; pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; - - if( isOpen(pPager->fd) ){ - void **ap = (void **)&pPager->xBusyHandler; - assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); - assert( ap[1]==pBusyHandlerArg ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); - } + ap = (void **)&pPager->xBusyHandler; + assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); + assert( ap[1]==pBusyHandlerArg ); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); } /* @@ -51582,6 +53651,30 @@ static void pagerFreeMapHdrs(Pager *pPager){ } } +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still where it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; +} + /* ** Shutdown the page cache. Free all memory and close all files. @@ -51598,8 +53691,7 @@ static void pagerFreeMapHdrs(Pager *pPager){ ** to the caller. */ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ - u8 *pTmp = (u8 *)pPager->pTmpSpace; - + u8 *pTmp = (u8*)pPager->pTmpSpace; assert( db || pagerUseWal(pPager)==0 ); assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); @@ -51608,11 +53700,17 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL - assert( db || pPager->pWal==0 ); - sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, - (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) - ); - pPager->pWal = 0; + { + u8 *a = 0; + assert( db || pPager->pWal==0 ); + if( db && 0==(db->flags & SQLITE_NoCkptOnClose) + && SQLITE_OK==databaseIsUnmoved(pPager) + ){ + a = pTmp; + } + sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); + pPager->pWal = 0; + } #endif pager_reset(pPager); if( MEMDB ){ @@ -52069,6 +54167,7 @@ static int pagerStress(void *p, PgHdr *pPg){ return SQLITE_OK; } + pPager->aStat[PAGER_STAT_SPILL]++; pPg->pDirty = 0; if( pagerUseWal(pPager) ){ /* Write a single frame for this page to the log. */ @@ -52174,6 +54273,11 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ +#ifdef SQLITE_ENABLE_DESERIALIZE + int memJM = 0; /* Memory journal mode */ +#else +# define memJM 0 +#endif int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ @@ -52301,7 +54405,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); - readOnly = (fout&SQLITE_OPEN_READONLY); +#ifdef SQLITE_ENABLE_DESERIALIZE + memJM = (fout&SQLITE_OPEN_MEMORY)!=0; +#endif + readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, ** choose a default page size in case we have to create the @@ -52432,7 +54539,7 @@ act_like_temp_file: setSectorSize(pPager); if( !useJournal ){ pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb ){ + }else if( memDb || memJM ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ @@ -52447,30 +54554,6 @@ act_like_temp_file: } -/* Verify that the database file has not be deleted or renamed out from -** under the pager. Return SQLITE_OK if the database is still were it ought -** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error -** code from sqlite3OsAccess()) if the database has gone missing. -*/ -static int databaseIsUnmoved(Pager *pPager){ - int bHasMoved = 0; - int rc; - - if( pPager->tempFile ) return SQLITE_OK; - if( pPager->dbSize==0 ) return SQLITE_OK; - assert( pPager->zFilename && pPager->zFilename[0] ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); - if( rc==SQLITE_NOTFOUND ){ - /* If the HAS_MOVED file-control is unimplemented, assume that the file - ** has not been moved. That is the historical behavior of SQLite: prior to - ** version 3.8.3, it never checked */ - rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bHasMoved ){ - rc = SQLITE_READONLY_DBMOVED; - } - return rc; -} - /* ** This function is called after transitioning from PAGER_UNLOCK to @@ -53059,7 +55142,7 @@ static int getPageMMap( } if( pPg==0 ){ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ + }else{ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); } if( pPg ){ @@ -53158,6 +55241,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){ assert( pPg->pgno==1 ); assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ pPager = pPg->pPager; + sqlite3PagerResetLockTimeout(pPager); sqlite3PcacheRelease(pPg); pagerUnlockIfUnused(pPager); } @@ -53753,12 +55837,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ */ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - - if( isOpen(pPager->fd) ){ - void *pArg = (void*)zMaster; - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - } + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; if( rc==SQLITE_OK && !pPager->noSync ){ assert( !MEMDB ); rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); @@ -53979,8 +56060,9 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( if( bBatch ){ if( rc==SQLITE_OK ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); - }else{ - sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); + } + if( rc!=SQLITE_OK ){ + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); } } @@ -54204,8 +56286,12 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ #endif /* -** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or -** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the +** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE, +** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation +** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because +** it was added later. +** +** Before returning, *pnVal is incremented by the ** current cache hit or miss count, according to the value of eStat. If the ** reset parameter is non-zero, the cache hit or miss count is zeroed before ** returning. @@ -54215,15 +56301,18 @@ SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, i assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS || eStat==SQLITE_DBSTATUS_CACHE_WRITE + || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 ); assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); - assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 + && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 ); - *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; + eStat -= SQLITE_DBSTATUS_CACHE_HIT; + *pnVal += pPager->aStat[eStat]; if( reset ){ - pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; + pPager->aStat[eStat] = 0; } } @@ -54427,6 +56516,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +/* +** Reset the lock timeout for pager. +*/ +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){ + int x = 0; + sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x); +} +#endif + /* ** Return the file handle for the journal file (if it exists). ** This will be either the rollback journal or the WAL file. @@ -54887,6 +56986,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); + sqlite3PagerResetLockTimeout(pPager); } return rc; } @@ -55247,6 +57347,10 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ ** on a network filesystem. All users of the database must be able to ** share memory. ** +** In the default unix and windows implementation, the wal-index is a mmapped +** file whose name is the database name with a "-shm" suffix added. For that +** reason, the wal-index is sometimes called the "shm" file. +** ** The wal-index is transient. After a crash, the wal-index can (and should ** be) reconstructed from the original WAL file. In fact, the VFS is required ** to either truncate or zero the header of the wal-index when the last @@ -55386,9 +57490,18 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; #define WALINDEX_MAX_VERSION 3007000 /* -** Indices of various locking bytes. WAL_NREADER is the number +** Index numbers for various locking bytes. WAL_NREADER is the number ** of available reader locks and should be at least 3. The default ** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5. +** +** Technically, the various VFSes are free to implement these locks however +** they see fit. However, compatibility is encouraged so that VFSes can +** interoperate. The standard implemention used on both unix and windows +** is for the index number to indicate a byte offset into the +** WalCkptInfo.aLock[] array in the wal-index header. In other words, all +** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which +** should be 120) is the location in the shm file for the first locking +** byte. */ #define WAL_WRITE_LOCK 0 #define WAL_ALL_BUT_WRITE 1 @@ -55512,7 +57625,6 @@ struct WalCkptInfo { #define WAL_FRAME_HDRSIZE 24 /* Size of write ahead log header, including checksum. */ -/* #define WAL_HDRSIZE 24 */ #define WAL_HDRSIZE 32 /* WAL magic value. Either this value, or the same value with the least @@ -55558,6 +57670,7 @@ struct Wal { u8 truncateOnCommit; /* True to truncate WAL file on commit */ u8 syncHeader; /* Fsync the WAL header if true */ u8 padToSectorBoundary; /* Pad transactions out to the next sector */ + u8 bShmUnreliable; /* SHM content is read-only and unreliable */ WalIndexHdr hdr; /* Wal-index header for current transaction */ u32 minFrame; /* Ignore wal frames before this one */ u32 iReCksum; /* On commit, recalculate checksums from here */ @@ -55647,11 +57760,20 @@ struct WalIterator { ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are ** numbered from zero. ** +** If the wal-index is currently smaller the iPage pages then the size +** of the wal-index might be increased, but only if it is safe to do +** so. It is safe to enlarge the wal-index if pWal->writeLock is true +** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE. +** ** If this call is successful, *ppPage is set to point to the wal-index ** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs, ** then an SQLite error code is returned and *ppPage is set to 0. */ -static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ +static SQLITE_NOINLINE int walIndexPageRealloc( + Wal *pWal, /* The WAL context */ + int iPage, /* The page we seek */ + volatile u32 **ppPage /* Write the page pointer here */ +){ int rc = SQLITE_OK; /* Enlarge the pWal->apWiData[] array if required */ @@ -55670,16 +57792,19 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ } /* Request a pointer to the required page from the VFS */ - if( pWal->apWiData[iPage]==0 ){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, - pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] - ); + assert( pWal->apWiData[iPage]==0 ); + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); + if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; + }else{ + rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, + pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] + ); + assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 ); + testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK ); + if( (rc&0xff)==SQLITE_READONLY ){ + pWal->readOnly |= WAL_SHM_RDONLY; if( rc==SQLITE_READONLY ){ - pWal->readOnly |= WAL_SHM_RDONLY; rc = SQLITE_OK; } } @@ -55689,6 +57814,16 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); return rc; } +static int walIndexPage( + Wal *pWal, /* The WAL context */ + int iPage, /* The page we seek */ + volatile u32 **ppPage /* Write the page pointer here */ +){ + if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ + return walIndexPageRealloc(pWal, iPage, ppPage); + } + return SQLITE_OK; +} /* ** Return a pointer to the WalCkptInfo structure in the wal-index. @@ -56202,7 +58337,6 @@ static int walIndexRecover(Wal *pWal){ i64 nSize; /* Size of log file */ u32 aFrameCksum[2] = {0, 0}; int iLock; /* Lock offset to lock for checkpoint */ - int nLock; /* Number of locks to hold */ /* Obtain an exclusive lock on all byte in the locking range not already ** locked by the caller. The caller is guaranteed to have locked the @@ -56215,11 +58349,17 @@ static int walIndexRecover(Wal *pWal){ assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); assert( pWal->writeLock ); iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; - nLock = SQLITE_SHM_NLOCK - iLock; - rc = walLockExclusive(pWal, iLock, nLock); + rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); + if( rc==SQLITE_OK ){ + rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + if( rc!=SQLITE_OK ){ + walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); + } + } if( rc ){ return rc; } + WALTRACE(("WAL%p: recovery begin...\n", pWal)); memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); @@ -56357,7 +58497,8 @@ finished: recovery_error: WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); - walUnlockExclusive(pWal, iLock, nLock); + walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); + walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); return rc; } @@ -56365,13 +58506,14 @@ recovery_error: ** Close an open wal-index. */ static void walIndexClose(Wal *pWal, int isDelete){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){ int i; for(i=0; inWiData; i++){ sqlite3_free((void *)pWal->apWiData[i]); pWal->apWiData[i] = 0; } - }else{ + } + if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){ sqlite3OsShmUnmap(pWal->pDbFd, isDelete); } } @@ -56658,8 +58800,9 @@ static void walIteratorFree(WalIterator *p){ /* ** Construct a WalInterator object that can be used to loop over all -** pages in the WAL in ascending order. The caller must hold the checkpoint -** lock. +** pages in the WAL following frame nBackfill in ascending order. Frames +** nBackfill or earlier may be included - excluding them is an optimization +** only. The caller must hold the checkpoint lock. ** ** On success, make *pp point to the newly allocated WalInterator object ** return SQLITE_OK. Otherwise, return an error code. If this routine @@ -56668,7 +58811,7 @@ static void walIteratorFree(WalIterator *p){ ** The calling routine should invoke walIteratorFree() to destroy the ** WalIterator object when it has finished with it. */ -static int walIteratorInit(Wal *pWal, WalIterator **pp){ +static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ WalIterator *p; /* Return value */ int nSegment; /* Number of segments to merge */ u32 iLast; /* Last frame in log */ @@ -56705,7 +58848,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ rc = SQLITE_NOMEM_BKPT; } - for(i=0; rc==SQLITE_OK && inBackfillhdr.mxFrame ){ - /* Allocate the iterator */ - rc = walIteratorInit(pWal, &pIter); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pIter ); - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); @@ -56904,7 +59041,13 @@ static int walCheckpoint( } } - if( pInfo->nBackfillnBackfillnBackfill, &pIter); + assert( rc==SQLITE_OK || pIter==0 ); + } + + if( pIter && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK ){ i64 nSize; /* Current size of database file */ @@ -57164,6 +59307,12 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){ return 0; } +/* +** This is the value that walTryBeginRead returns when it needs to +** be retried. +*/ +#define WAL_RETRY (-1) + /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the @@ -57187,9 +59336,29 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ assert( pChanged ); rc = walIndexPage(pWal, 0, &page0); if( rc!=SQLITE_OK ){ - return rc; - }; - assert( page0 || pWal->writeLock==0 ); + assert( rc!=SQLITE_READONLY ); /* READONLY changed to OK in walIndexPage */ + if( rc==SQLITE_READONLY_CANTINIT ){ + /* The SQLITE_READONLY_CANTINIT return means that the shared-memory + ** was openable but is not writable, and this thread is unable to + ** confirm that another write-capable connection has the shared-memory + ** open, and hence the content of the shared-memory is unreliable, + ** since the shared-memory might be inconsistent with the WAL file + ** and there is no writer on hand to fix it. */ + assert( page0==0 ); + assert( pWal->writeLock==0 ); + assert( pWal->readOnly & WAL_SHM_RDONLY ); + pWal->bShmUnreliable = 1; + pWal->exclusiveMode = WAL_HEAPMEMORY_MODE; + *pChanged = 1; + }else{ + return rc; /* Any other non-OK return is just an error */ + } + }else{ + /* page0 can be NULL if the SHM is zero bytes in size and pWal->writeLock + ** is zero, which prevents the SHM from growing */ + testcase( page0!=0 ); + } + assert( page0!=0 || pWal->writeLock==0 ); /* If the first page of the wal-index has been mapped, try to read the ** wal-index header immediately, without holding any lock. This usually @@ -57203,7 +59372,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ */ assert( badHdr==0 || pWal->writeLock==0 ); if( badHdr ){ - if( pWal->readOnly & WAL_SHM_RDONLY ){ + if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){ if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; @@ -57233,15 +59402,193 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ rc = SQLITE_CANTOPEN_BKPT; } + if( pWal->bShmUnreliable ){ + if( rc!=SQLITE_OK ){ + walIndexClose(pWal, 0); + pWal->bShmUnreliable = 0; + assert( pWal->nWiData>0 && pWal->apWiData[0]==0 ); + /* walIndexRecover() might have returned SHORT_READ if a concurrent + ** writer truncated the WAL out from under it. If that happens, it + ** indicates that a writer has fixed the SHM file for us, so retry */ + if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; + } + pWal->exclusiveMode = WAL_NORMAL_MODE; + } return rc; } /* -** This is the value that walTryBeginRead returns when it needs to -** be retried. +** Open a transaction in a connection where the shared-memory is read-only +** and where we cannot verify that there is a separate write-capable connection +** on hand to keep the shared-memory up-to-date with the WAL file. +** +** This can happen, for example, when the shared-memory is implemented by +** memory-mapping a *-shm file, where a prior writer has shut down and +** left the *-shm file on disk, and now the present connection is trying +** to use that database but lacks write permission on the *-shm file. +** Other scenarios are also possible, depending on the VFS implementation. +** +** Precondition: +** +** The *-wal file has been read and an appropriate wal-index has been +** constructed in pWal->apWiData[] using heap memory instead of shared +** memory. +** +** If this function returns SQLITE_OK, then the read transaction has +** been successfully opened. In this case output variable (*pChanged) +** is set to true before returning if the caller should discard the +** contents of the page cache before proceeding. Or, if it returns +** WAL_RETRY, then the heap memory wal-index has been discarded and +** the caller should retry opening the read transaction from the +** beginning (including attempting to map the *-shm file). +** +** If an error occurs, an SQLite error code is returned. */ -#define WAL_RETRY (-1) +static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ + i64 szWal; /* Size of wal file on disk in bytes */ + i64 iOffset; /* Current offset when reading wal file */ + u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ + u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ + int szFrame; /* Number of bytes in buffer aFrame[] */ + u8 *aData; /* Pointer to data part of aFrame buffer */ + volatile void *pDummy; /* Dummy argument for xShmMap */ + int rc; /* Return code */ + u32 aSaveCksum[2]; /* Saved copy of pWal->hdr.aFrameCksum */ + + assert( pWal->bShmUnreliable ); + assert( pWal->readOnly & WAL_SHM_RDONLY ); + assert( pWal->nWiData>0 && pWal->apWiData[0] ); + + /* Take WAL_READ_LOCK(0). This has the effect of preventing any + ** writers from running a checkpoint, but does not stop them + ** from running recovery. */ + rc = walLockShared(pWal, WAL_READ_LOCK(0)); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_BUSY ) rc = WAL_RETRY; + goto begin_unreliable_shm_out; + } + pWal->readLock = 0; + + /* Check to see if a separate writer has attached to the shared-memory area, + ** thus making the shared-memory "reliable" again. Do this by invoking + ** the xShmMap() routine of the VFS and looking to see if the return + ** is SQLITE_READONLY instead of SQLITE_READONLY_CANTINIT. + ** + ** If the shared-memory is now "reliable" return WAL_RETRY, which will + ** cause the heap-memory WAL-index to be discarded and the actual + ** shared memory to be used in its place. + ** + ** This step is important because, even though this connection is holding + ** the WAL_READ_LOCK(0) which prevents a checkpoint, a writer might + ** have already checkpointed the WAL file and, while the current + ** is active, wrap the WAL and start overwriting frames that this + ** process wants to use. + ** + ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has + ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY + ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations, + ** even if some external agent does a "chmod" to make the shared-memory + ** writable by us, until sqlite3OsShmUnmap() has been called. + ** This is a requirement on the VFS implementation. + */ + rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy); + assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */ + if( rc!=SQLITE_READONLY_CANTINIT ){ + rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc); + goto begin_unreliable_shm_out; + } + + /* We reach this point only if the real shared-memory is still unreliable. + ** Assume the in-memory WAL-index substitute is correct and load it + ** into pWal->hdr. + */ + memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + /* Make sure some writer hasn't come in and changed the WAL file out + ** from under us, then disconnected, while we were not looking. + */ + rc = sqlite3OsFileSize(pWal->pWalFd, &szWal); + if( rc!=SQLITE_OK ){ + goto begin_unreliable_shm_out; + } + if( szWalhdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY); + goto begin_unreliable_shm_out; + } + + /* Check the salt keys at the start of the wal file still match. */ + rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); + if( rc!=SQLITE_OK ){ + goto begin_unreliable_shm_out; + } + if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){ + /* Some writer has wrapped the WAL file while we were not looking. + ** Return WAL_RETRY which will cause the in-memory WAL-index to be + ** rebuilt. */ + rc = WAL_RETRY; + goto begin_unreliable_shm_out; + } + + /* Allocate a buffer to read frames into */ + szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE; + aFrame = (u8 *)sqlite3_malloc64(szFrame); + if( aFrame==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto begin_unreliable_shm_out; + } + aData = &aFrame[WAL_FRAME_HDRSIZE]; + + /* Check to see if a complete transaction has been appended to the + ** wal file since the heap-memory wal-index was created. If so, the + ** heap-memory wal-index is discarded and WAL_RETRY returned to + ** the caller. */ + aSaveCksum[0] = pWal->hdr.aFrameCksum[0]; + aSaveCksum[1] = pWal->hdr.aFrameCksum[1]; + for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage); + iOffset+szFrame<=szWal; + iOffset+=szFrame + ){ + u32 pgno; /* Database page number for frame */ + u32 nTruncate; /* dbsize field from frame header */ + + /* Read and decode the next log frame. */ + rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); + if( rc!=SQLITE_OK ) break; + if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break; + + /* If nTruncate is non-zero, then a complete transaction has been + ** appended to this wal file. Set rc to WAL_RETRY and break out of + ** the loop. */ + if( nTruncate ){ + rc = WAL_RETRY; + break; + } + } + pWal->hdr.aFrameCksum[0] = aSaveCksum[0]; + pWal->hdr.aFrameCksum[1] = aSaveCksum[1]; + + begin_unreliable_shm_out: + sqlite3_free(aFrame); + if( rc!=SQLITE_OK ){ + int i; + for(i=0; inWiData; i++){ + sqlite3_free((void*)pWal->apWiData[i]); + pWal->apWiData[i] = 0; + } + pWal->bShmUnreliable = 0; + sqlite3WalEndReadTransaction(pWal); + *pChanged = 1; + } + return rc; +} /* ** Attempt to start a read transaction. This might fail due to a race or @@ -57257,7 +59604,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ ** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() ** to make a copy of the wal-index header into pWal->hdr. If the ** wal-index header has changed, *pChanged is set to 1 (as an indication -** to the caller that the local paget cache is obsolete and needs to be +** to the caller that the local page cache is obsolete and needs to be ** flushed.) When useWal==1, the wal-index header is assumed to already ** be loaded and the pChanged parameter is unused. ** @@ -57303,6 +59650,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ assert( pWal->readLock<0 ); /* Not currently locked */ + /* useWal may only be set for read/write connections */ + assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 ); + /* Take steps to avoid spinning forever if there is a protocol error. ** ** Circumstances that cause a RETRY should only last for the briefest @@ -57331,7 +59681,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } if( !useWal ){ - rc = walIndexReadHdr(pWal, pChanged); + assert( rc==SQLITE_OK ); + if( pWal->bShmUnreliable==0 ){ + rc = walIndexReadHdr(pWal, pChanged); + } if( rc==SQLITE_BUSY ){ /* If there is not a recovery running in another thread or process ** then convert BUSY errors to WAL_RETRY. If recovery is known to @@ -57360,13 +59713,17 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ if( rc!=SQLITE_OK ){ return rc; } + else if( pWal->bShmUnreliable ){ + return walBeginShmUnreliable(pWal, pChanged); + } } + assert( pWal->nWiData>0 ); + assert( pWal->apWiData[0]!=0 ); pInfo = walCkptInfo(pWal); - if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame + if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame #ifdef SQLITE_ENABLE_SNAPSHOT - && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0 - || 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr))) + && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) #endif ){ /* The WAL has been completely backfilled (or it is empty). @@ -57437,7 +59794,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } if( mxI==0 ){ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); - return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; + return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; } rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); @@ -57709,7 +60066,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( ** then the WAL is ignored by the reader so return early, as if the ** WAL were empty. */ - if( iLast==0 || pWal->readLock==0 ){ + if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){ *piRead = 0; return SQLITE_OK; } @@ -57740,7 +60097,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( ** table after the current read-transaction had started. */ iMinHash = walFramePage(pWal->minFrame); - for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){ + for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ volatile ht_slot *aHash; /* Pointer to hash table */ volatile u32 *aPgno; /* Pointer to array of page numbers */ u32 iZero; /* Frame number corresponding to aPgno[0] */ @@ -57763,6 +60120,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( return SQLITE_CORRUPT_BKPT; } } + if( iRead ) break; } #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT @@ -57772,8 +60130,8 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( { u32 iRead2 = 0; u32 iTest; - assert( pWal->minFrame>0 ); - for(iTest=iLast; iTest>=pWal->minFrame; iTest--){ + assert( pWal->bShmUnreliable || pWal->minFrame>0 ); + for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){ if( walFramePgno(pWal, iTest)==pgno ){ iRead2 = iTest; break; @@ -58549,24 +60907,24 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); if( op==0 ){ - if( pWal->exclusiveMode ){ - pWal->exclusiveMode = 0; + if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ + pWal->exclusiveMode = WAL_NORMAL_MODE; if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ - pWal->exclusiveMode = 1; + pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } - rc = pWal->exclusiveMode==0; + rc = pWal->exclusiveMode==WAL_NORMAL_MODE; }else{ /* Already in locking_mode=NORMAL */ rc = 0; } }else if( op>0 ){ - assert( pWal->exclusiveMode==0 ); + assert( pWal->exclusiveMode==WAL_NORMAL_MODE ); assert( pWal->readLock>=0 ); walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->exclusiveMode = 1; + pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; rc = 1; }else{ - rc = pWal->exclusiveMode==0; + rc = pWal->exclusiveMode==WAL_NORMAL_MODE; } return rc; } @@ -59177,20 +61535,20 @@ struct BtCursor { u8 curFlags; /* zero or more BTCF_* flags defined below */ u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ u8 hints; /* As configured by CursorSetHints() */ - int nOvflAlloc; /* Allocated size of aOverflow[] array */ - Btree *pBtree; /* The Btree to which this cursor belongs */ - BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext; /* Forms a linked list of all cursors */ - Pgno *aOverflow; /* Cache of overflow page locations */ - CellInfo info; /* A parse of the cell we are pointing at */ - i64 nKey; /* Size of pKey, or last integer key */ - void *pKey; /* Saved key that was cursor last known position */ - Pgno pgnoRoot; /* The root page of this tree */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ** Error code if eState==CURSOR_FAULT */ + Btree *pBtree; /* The Btree to which this cursor belongs */ + Pgno *aOverflow; /* Cache of overflow page locations */ + void *pKey; /* Saved key that was cursor last known position */ /* All fields above are zeroed when the cursor is allocated. See ** sqlite3BtreeCursorZero(). Fields that follow must be manually ** initialized. */ +#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext; /* Forms a linked list of all cursors */ + CellInfo info; /* A parse of the cell we are pointing at */ + i64 nKey; /* Size of pKey, or last integer key */ + Pgno pgnoRoot; /* The root page of this tree */ i8 iPage; /* Index of current page in apPage */ u8 curIntKey; /* Value of apPage[0]->intKey */ u16 ix; /* Current index for apPage[iPage] */ @@ -59240,8 +61598,8 @@ struct BtCursor { ** Do nothing else with this cursor. Any attempt to use the cursor ** should return the error code stored in BtCursor.skipNext */ -#define CURSOR_INVALID 0 -#define CURSOR_VALID 1 +#define CURSOR_VALID 0 +#define CURSOR_INVALID 1 #define CURSOR_SKIPNEXT 2 #define CURSOR_REQUIRESEEK 3 #define CURSOR_FAULT 4 @@ -59558,10 +61916,10 @@ static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ skipOk = 0; } } - db->skipBtreeMutex = skipOk; + db->noSharedCache = skipOk; } SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeEnterAll(db); + if( db->noSharedCache==0 ) btreeEnterAll(db); } static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ int i; @@ -59573,7 +61931,7 @@ static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ } } SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); + if( db->noSharedCache==0 ) btreeLeaveAll(db); } #ifndef NDEBUG @@ -59786,6 +62144,34 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){ #define hasReadConflicts(a, b) 0 #endif +/* +** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single +** (MemPage*) as an argument. The (MemPage*) must not be NULL. +** +** If SQLITE_DEBUG is not defined, then this macro is equivalent to +** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message +** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented +** with the page number and filename associated with the (MemPage*). +*/ +#ifdef SQLITE_DEBUG +int corruptPageError(int lineno, MemPage *p){ + char *zMsg; + sqlite3BeginBenignMalloc(); + zMsg = sqlite3_mprintf("database corruption page %d of %s", + (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) + ); + sqlite3EndBenignMalloc(); + if( zMsg ){ + sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); + } + sqlite3_free(zMsg); + return SQLITE_CORRUPT_BKPT; +} +# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) +#else +# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) +#endif + #ifndef SQLITE_OMIT_SHARED_CACHE #ifdef SQLITE_DEBUG @@ -60510,7 +62896,11 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){ ** back to where it ought to be if this routine returns true. */ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ - return pCur->eState!=CURSOR_VALID; + assert( EIGHT_BYTE_ALIGNMENT(pCur) + || pCur==sqlite3BtreeFakeValidCursor() ); + assert( offsetof(BtCursor, eState)==0 ); + assert( sizeof(pCur->eState)==1 ); + return CURSOR_VALID != *(u8*)pCur; } /* @@ -61074,7 +63464,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); if( top>=iFree ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFree2 ){ assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */ @@ -61108,13 +63498,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** if PRAGMA cell_size_check=ON. */ if( pciCellLast ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pc>=iCellFirst && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrkusableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); testcase( cbrk+size==usableSize ); @@ -61134,7 +63524,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ defragment_out: if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -61178,7 +63568,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ testcase( x==4 ); testcase( x==3 ); if( size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); + *pRc = SQLITE_CORRUPT_PAGE(pPg); return 0; }else if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total @@ -61201,7 +63591,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ if( pcpgno); + *pRc = SQLITE_CORRUPT_PAGE(pPg); } return 0; @@ -61249,7 +63639,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } @@ -61339,12 +63729,12 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ while( (iFreeBlk = get2byte(&data[iPtr]))pgno); + return SQLITE_CORRUPT_PAGE(pPage); } iPtr = iFreeBlk; } if( iFreeBlk>pPage->pBt->usableSize-4 ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( iFreeBlk>iPtr || iFreeBlk==0 ); @@ -61356,10 +63746,10 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); if( iEnd > pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); @@ -61372,13 +63762,13 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } x = get2byte(&data[hdr+5]); @@ -61386,7 +63776,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iStartpgno); + if( iStartpgno); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; @@ -61500,7 +63890,7 @@ static int btreeInitPage(MemPage *pPage){ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ if( decodeFlags(pPage, data[hdr]) ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); @@ -61519,7 +63909,7 @@ static int btreeInitPage(MemPage *pPage){ pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } testcase( pPage->nCell==MX_CELL(pBt) ); /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only @@ -61547,12 +63937,12 @@ static int btreeInitPage(MemPage *pPage){ testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pciCellLast ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } sz = pPage->xCellSize(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } if( !pPage->leaf ) iCellLast++; @@ -61570,12 +63960,12 @@ static int btreeInitPage(MemPage *pPage){ /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } while( 1 ){ if( pc>iCellLast ){ /* Freeblock off the end of the page */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); @@ -61585,11 +63975,11 @@ static int btreeInitPage(MemPage *pPage){ } if( next>0 ){ /* Freeblock not in ascending order */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( pc+size>(unsigned int)usableSize ){ /* Last freeblock extends past page end */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } @@ -61601,7 +63991,7 @@ static int btreeInitPage(MemPage *pPage){ ** area, according to the page header, lies within the page. */ if( nFree>usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->nFree = (u16)(nFree - iCellFirst); pPage->isInit = 1; @@ -61877,7 +64267,8 @@ static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, + sqlite3PagerFile(pBt->pPager)); } /* @@ -62055,7 +64446,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( } pBt->openFlags = (u8)flags; pBt->db = db; - sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); + sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; pBt->pCursor = 0; @@ -62617,6 +65008,10 @@ static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ # define setDefaultSyncFlag(pBt,safety_level) #endif +/* Forward declaration */ +static int newDatabase(BtShared*); + + /* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. @@ -62648,6 +65043,9 @@ static int lockBtree(BtShared *pBt){ if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ nPage = nPageFile; } + if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ + nPage = 0; + } if( nPage>0 ){ u32 pageSize; u32 usableSize; @@ -63018,6 +65416,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); + sqlite3PagerResetLockTimeout(pBt->pPager); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ @@ -63132,7 +65531,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(pPage->aData, iTo); }else{ @@ -63151,7 +65550,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); @@ -63169,7 +65568,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } @@ -63991,7 +66390,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ ** of run-time by skipping the initialization of those elements. */ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ - memset(p, 0, offsetof(BtCursor, iPage)); + memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT)); } /* @@ -64034,11 +66433,19 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ ** Using this cache reduces the number of calls to btreeParseCell(). */ #ifndef NDEBUG + static int cellInfoEqual(CellInfo *a, CellInfo *b){ + if( a->nKey!=b->nKey ) return 0; + if( a->pPayload!=b->pPayload ) return 0; + if( a->nPayload!=b->nPayload ) return 0; + if( a->nLocal!=b->nLocal ) return 0; + if( a->nSize!=b->nSize ) return 0; + return 1; + } static void assertCellInfo(BtCursor *pCur){ CellInfo info; memset(&info, 0, sizeof(info)); btreeParseCell(pCur->pPage, pCur->ix, &info); - assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); + assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) ); } #else #define assertCellInfo(x) @@ -64081,6 +66488,20 @@ SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ return pCur->info.nKey; } +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +/* +** Return the offset into the database file for the start of the +** payload to which the cursor is pointing. +*/ +SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + getCellInfo(pCur); + return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + + (i64)(pCur->info.pPayload - pCur->pPage->aData); +} +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ + /* ** Return the number of bytes of payload for the entry that pCur is ** currently pointing to. For table btrees, this will be the amount @@ -64267,7 +66688,7 @@ static int accessPayload( ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } /* Check if data must be read/written to/from the btree page itself. */ @@ -64300,14 +66721,15 @@ static int accessPayload( */ if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - if( nOvfl>pCur->nOvflAlloc ){ + if( pCur->aOverflow==0 + || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) + ){ Pgno *aNew = (Pgno*)sqlite3Realloc( pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ return SQLITE_NOMEM_BKPT; }else{ - pCur->nOvflAlloc = nOvfl*2; pCur->aOverflow = aNew; } } @@ -64415,7 +66837,7 @@ static int accessPayload( if( rc==SQLITE_OK && amt>0 ){ /* Overflow chain ends prematurely */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } return rc; } @@ -64693,7 +67115,7 @@ static int moveToRoot(BtCursor *pCur){ ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_PGNO(pCur->pPage->pgno); + return SQLITE_CORRUPT_PAGE(pCur->pPage); } skip_init: @@ -64966,7 +67388,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } } @@ -65040,7 +67462,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 ){ - rc = SQLITE_CORRUPT_PGNO(pPage->pgno); + rc = SQLITE_CORRUPT_PAGE(pPage); goto moveto_finish; } pCellKey = sqlite3Malloc( nCell+18 ); @@ -65821,9 +68243,8 @@ static void freePage(MemPage *pPage, int *pRC){ } /* -** Free any overflow pages associated with the given Cell. Write the -** local Cell size (the number of bytes on the original page, omitting -** overflow) into *pnSize. +** Free any overflow pages associated with the given Cell. Store +** size information about the cell in pInfo. */ static int clearCell( MemPage *pPage, /* The page that contains the Cell */ @@ -65841,9 +68262,11 @@ static int clearCell( if( pInfo->nLocal==pInfo->nPayload ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } - if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ + testcase( pCell + pInfo->nSize == pPage->aDataEnd ); + testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); + if( pCell + pInfo->nSize > pPage->aDataEnd ){ /* Cell extends past end of page */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); pBt = pPage->pBt; @@ -67027,7 +69450,7 @@ static int balance_nonroot( } /* Load b.apCell[] with pointers to all cells in pOld. If pOld - ** constains overflow cells, include them in the b.apCell[] array + ** contains overflow cells, include them in the b.apCell[] array ** in the correct spot. ** ** Note that when there are multiple overflow cells, it is always the @@ -67767,6 +70190,94 @@ static int balance(BtCursor *pCur){ return rc; } +/* Overwrite content from pX into pDest. Only do the write if the +** content is different from what is already there. +*/ +static int btreeOverwriteContent( + MemPage *pPage, /* MemPage on which writing will occur */ + u8 *pDest, /* Pointer to the place to start writing */ + const BtreePayload *pX, /* Source of data to write */ + int iOffset, /* Offset of first byte to write */ + int iAmt /* Number of bytes to be written */ +){ + int nData = pX->nData - iOffset; + if( nData<=0 ){ + /* Overwritting with zeros */ + int i; + for(i=0; ipDbPage); + if( rc ) return rc; + memset(pDest + i, 0, iAmt - i); + } + }else{ + if( nDatapData) + iOffset, iAmt)!=0 ){ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt); + } + } + return SQLITE_OK; +} + +/* +** Overwrite the cell that cursor pCur is pointing to with fresh content +** contained in pX. +*/ +static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ + int iOffset; /* Next byte of pX->pData to write */ + int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ + int rc; /* Return code */ + MemPage *pPage = pCur->pPage; /* Page being written */ + BtShared *pBt; /* Btree */ + Pgno ovflPgno; /* Next overflow page to write */ + u32 ovflPageSize; /* Size to write on overflow page */ + + if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ + return SQLITE_CORRUPT_BKPT; + } + /* Overwrite the local portion first */ + rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, + 0, pCur->info.nLocal); + if( rc ) return rc; + if( pCur->info.nLocal==nTotal ) return SQLITE_OK; + + /* Now overwrite the overflow pages */ + iOffset = pCur->info.nLocal; + assert( nTotal>=0 ); + assert( iOffset>=0 ); + ovflPgno = get4byte(pCur->info.pPayload + iOffset); + pBt = pPage->pBt; + ovflPageSize = pBt->usableSize - 4; + do{ + rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); + if( rc ) return rc; + if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + if( iOffset+ovflPageSize<(u32)nTotal ){ + ovflPgno = get4byte(pPage->aData); + }else{ + ovflPageSize = nTotal - iOffset; + } + rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, + iOffset, ovflPageSize); + } + sqlite3PagerUnref(pPage->pDbPage); + if( rc ) return rc; + iOffset += ovflPageSize; + }while( iOffsetpgnoRoot, pX->nKey, 0); /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing - ** to a row with the same key as the new entry being inserted. */ - assert( (flags & BTREE_SAVEPOSITION)==0 || - ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) ); + ** to a row with the same key as the new entry being inserted. + */ +#ifdef SQLITE_DEBUG + if( flags & BTREE_SAVEPOSITION ){ + assert( pCur->curFlags & BTCF_ValidNKey ); + assert( pX->nKey==pCur->info.nKey ); + assert( pCur->info.nSize!=0 ); + assert( loc==0 ); + } +#endif - /* If the cursor is currently on the last row and we are appending a - ** new row onto the end, set the "loc" to avoid an unnecessary - ** btreeMoveto() call */ + /* On the other hand, BTREE_SAVEPOSITION==0 does not imply + ** that the cursor is not pointing to a row to be overwritten. + ** So do a complete check. + */ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ - loc = 0; + /* The cursor is pointing to the entry that is to be + ** overwritten */ + assert( pX->nData>=0 && pX->nZero>=0 ); + if( pCur->info.nSize!=0 + && pCur->info.nPayload==(u32)pX->nData+pX->nZero + ){ + /* New entry is the same size as the old. Do an overwrite */ + return btreeOverwriteCell(pCur, pX); + } + assert( loc==0 ); }else if( loc==0 ){ + /* The cursor is *not* pointing to the cell to be overwritten, nor + ** to an adjacent cell. Move the cursor so that it is pointing either + ** to the cell to be overwritten or an adjacent cell. + */ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); if( rc ) return rc; } - }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ - if( pX->nMem ){ - UnpackedRecord r; - r.pKeyInfo = pCur->pKeyInfo; - r.aMem = pX->aMem; - r.nField = pX->nMem; - r.default_rc = 0; - r.errCode = 0; - r.r1 = 0; - r.r2 = 0; - r.eqSeen = 0; - rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); - }else{ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); + }else{ + /* This is an index or a WITHOUT ROWID table */ + + /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing + ** to a row with the same key as the new entry being inserted. + */ + assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); + + /* If the cursor is not already pointing either to the cell to be + ** overwritten, or if a new cell is being inserted, if the cursor is + ** not pointing to an immediately adjacent cell, then move the cursor + ** so that it does. + */ + if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ + if( pX->nMem ){ + UnpackedRecord r; + r.pKeyInfo = pCur->pKeyInfo; + r.aMem = pX->aMem; + r.nField = pX->nMem; + r.default_rc = 0; + r.errCode = 0; + r.r1 = 0; + r.r2 = 0; + r.eqSeen = 0; + rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); + }else{ + rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); + } + if( rc ) return rc; } - if( rc ) return rc; + + /* If the cursor is currently pointing to an entry to be overwritten + ** and the new content is the same as as the old, then use the + ** overwrite optimization. + */ + if( loc==0 ){ + getCellInfo(pCur); + if( pCur->info.nKey==pX->nKey ){ + BtreePayload x2; + x2.pData = pX->pKey; + x2.nData = pX->nKey; + x2.nZero = 0; + return btreeOverwriteCell(pCur, &x2); + } + } + } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); @@ -68724,14 +71286,14 @@ static void checkAppendMsg( pCheck->nErr++; va_start(ap, zFormat); if( pCheck->errMsg.nChar ){ - sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); + sqlite3_str_append(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ - sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); + sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); } - sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); + sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); va_end(ap); - if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ + if( pCheck->errMsg.accError==SQLITE_NOMEM ){ pCheck->mallocFailed = 1; } } @@ -69315,11 +71877,11 @@ integrity_ck_cleanup: sqlite3PageFree(sCheck.heap); sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ - sqlite3StrAccumReset(&sCheck.errMsg); + sqlite3_str_reset(&sCheck.errMsg); sCheck.nErr++; } *pnErr = sCheck.nErr; - if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); + if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg); /* Make sure this analysis did not leave any unref() pages. */ assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); sqlite3BtreeLeave(p); @@ -70462,7 +73024,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ if( p->flags & MEM_Null ){ /* Cannot be both MEM_Null and some other type */ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob - |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 ); + |MEM_RowSet|MEM_Frame|MEM_Agg))==0 ); /* If MEM_Null is set, then either the value is a pure NULL (the usual ** case) or it is a pointer set using sqlite3_bind_pointer() or @@ -70512,6 +73074,51 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ } #endif +#ifdef SQLITE_DEBUG +/* +** Check that string value of pMem agrees with its integer or real value. +** +** A single int or real value always converts to the same strings. But +** many different strings can be converted into the same int or real. +** If a table contains a numeric value and an index is based on the +** corresponding string value, then it is important that the string be +** derived from the numeric value, not the other way around, to ensure +** that the index and table are consistent. See ticket +** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for +** an example. +** +** This routine looks at pMem to verify that if it has both a numeric +** representation and a string representation then the string rep has +** been derived from the numeric and not the other way around. It returns +** true if everything is ok and false if there is a problem. +** +** This routine is for use inside of assert() statements only. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemConsistentDualRep(Mem *p){ + char zBuf[100]; + char *z; + int i, j, incr; + if( (p->flags & MEM_Str)==0 ) return 1; + if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1; + if( p->flags & MEM_Int ){ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i); + }else{ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r); + } + z = p->z; + i = j = 0; + incr = 1; + if( p->enc!=SQLITE_UTF8 ){ + incr = 2; + if( p->enc==SQLITE_UTF16BE ) z++; + } + while( zBuf[j] ){ + if( zBuf[j++]!=z[i] ) return 0; + i += incr; + } + return 1; +} +#endif /* SQLITE_DEBUG */ /* ** If pMem is an object with a valid string representation, this routine @@ -70769,26 +73376,24 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ ** otherwise. */ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ - int rc = SQLITE_OK; - if( ALWAYS(pFunc && pFunc->xFinalize) ){ - sqlite3_context ctx; - Mem t; - assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - memset(&ctx, 0, sizeof(ctx)); - memset(&t, 0, sizeof(t)); - t.flags = MEM_Null; - t.db = pMem->db; - ctx.pOut = &t; - ctx.pMem = pMem; - ctx.pFunc = pFunc; - pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ - assert( (pMem->flags & MEM_Dyn)==0 ); - if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); - memcpy(pMem, &t, sizeof(t)); - rc = ctx.isError; - } - return rc; + sqlite3_context ctx; + Mem t; + assert( pFunc!=0 ); + assert( pFunc->xFinalize!=0 ); + assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + memset(&ctx, 0, sizeof(ctx)); + memset(&t, 0, sizeof(t)); + t.flags = MEM_Null; + t.db = pMem->db; + ctx.pOut = &t; + ctx.pMem = pMem; + ctx.pFunc = pFunc; + pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ + assert( (pMem->flags & MEM_Dyn)==0 ); + if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); + memcpy(pMem, &t, sizeof(t)); + return ctx.isError; } /* @@ -70948,6 +73553,16 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ } } +/* +** Return 1 if pMem represents true, and return 0 if pMem represents false. +** Return the value ifNull if pMem is NULL. +*/ +SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ + if( pMem->flags & MEM_Int ) return pMem->u.i!=0; + if( pMem->flags & MEM_Null ) return ifNull; + return sqlite3VdbeRealValue(pMem)!=0.0; +} + /* ** The MEM structure is already a MEM_Real. Try to also make it a ** MEM_Int if we can. @@ -71003,6 +73618,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ return SQLITE_OK; } +/* Compare a floating point value to an integer. Return true if the two +** values are the same within the precision of the floating point value. +** +** For some versions of GCC on 32-bit machines, if you do the more obvious +** comparison of "r1==(double)i" you sometimes get an answer of false even +** though the r1 and (double)i values are bit-for-bit the same. +*/ +static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ + double r2 = (double)i; + return memcmp(&r1, &r2, sizeof(r1))==0; +} + /* ** Convert pMem so that it has types MEM_Real or MEM_Int or both. ** Invalidate any prior representations. @@ -71022,7 +73649,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ }else{ i64 i = pMem->u.i; sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( rc==1 && pMem->u.r==(double)i ){ + if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){ pMem->u.i = i; MemSetTypeFlag(pMem, MEM_Int); }else{ @@ -71154,7 +73781,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ } /* A no-op destructor */ -static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } +SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } /* ** Set the value stored in *pMem should already be a NULL. @@ -71505,6 +74132,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 || pVal->db->mallocFailed ); if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ + assert( sqlite3VdbeMemConsistentDualRep(pVal) ); return pVal->z; }else{ return 0; @@ -71527,6 +74155,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); assert( (pVal->flags & MEM_RowSet)==0 ); if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ + assert( sqlite3VdbeMemConsistentDualRep(pVal) ); return pVal->z; } if( pVal->flags&MEM_Null ){ @@ -71742,7 +74371,11 @@ static int valueFromExpr( assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; +#if defined(SQLITE_ENABLE_STAT3_OR_STAT4) + if( op==TK_REGISTER ) op = pExpr->op2; +#else if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; +#endif /* Compressed expressions only appear when parsing the DEFAULT clause ** on a table column definition, and hence only when pCtx==0. This @@ -71826,18 +74459,25 @@ static int valueFromExpr( 0, SQLITE_DYNAMIC); } #endif - #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 else if( op==TK_FUNCTION && pCtx!=0 ){ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); } #endif + else if( op==TK_TRUEFALSE ){ + pVal = valueNew(db, pCtx); + pVal->flags = MEM_Int; + pVal->u.i = pExpr->u.zToken[4]==0; + } *ppVal = pVal; return rc; no_mem: - sqlite3OomFault(db); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx==0 || pCtx->pParse->nErr==0 ) +#endif + sqlite3OomFault(db); sqlite3DbFree(db, zVal); assert( *ppVal==0 ); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 @@ -72487,6 +75127,49 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8( return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); } +#ifndef SQLITE_OMIT_EXPLAIN +/* +** Return the address of the current EXPLAIN QUERY PLAN baseline. +** 0 means "none". +*/ +SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){ + VdbeOp *pOp; + if( pParse->addrExplain==0 ) return 0; + pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); + return pOp->p2; +} + +/* +** Add a new OP_Explain opcode. +** +** If the bPush flag is true, then make this opcode the parent for +** subsequent Explains until sqlite3VdbeExplainPop() is called. +*/ +SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ + if( pParse->explain==2 ){ + char *zMsg; + Vdbe *v = pParse->pVdbe; + va_list ap; + int iThis; + va_start(ap, zFmt); + zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); + va_end(ap); + v = pParse->pVdbe; + iThis = v->nOp; + sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, + zMsg, P4_DYNAMIC); + if( bPush) pParse->addrExplain = iThis; + } +} + +/* +** Pop the EXPLAIN QUERY PLAN stack one level. +*/ +SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){ + pParse->addrExplain = sqlite3VdbeExplainParent(pParse); +} +#endif /* SQLITE_OMIT_EXPLAIN */ + /* ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees @@ -72576,10 +75259,29 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ assert( jnLabel ); assert( j>=0 ); if( p->aLabel ){ +#ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + printf("RESOLVE LABEL %d to %d\n", x, v->nOp); + } +#endif + assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */ p->aLabel[j] = v->nOp; } } +#ifdef SQLITE_COVERAGE_TEST +/* +** Return TRUE if and only if the label x has already been resolved. +** Return FALSE (zero) if label x is still unresolved. +** +** This routine is only used inside of testcase() macros, and so it +** only exists when measuring test coverage. +*/ +SQLITE_PRIVATE int sqlite3VdbeLabelHasBeenResolved(Vdbe *v, int x){ + return v->pParse->aLabel && v->pParse->aLabel[ADDR(x)]>=0; +} +#endif /* SQLITE_COVERAGE_TEST */ + /* ** Mark the VDBE as one that can only be run one time. */ @@ -72725,6 +75427,32 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ } #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ +#ifdef SQLITE_DEBUG +/* +** Increment the nWrite counter in the VDBE if the cursor is not an +** ephemeral cursor, or if the cursor argument is NULL. +*/ +SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){ + if( pC==0 + || (pC->eCurType!=CURTYPE_SORTER + && pC->eCurType!=CURTYPE_PSEUDO + && !pC->isEphemeral) + ){ + p->nWrite++; + } +} +#endif + +#ifdef SQLITE_DEBUG +/* +** Assert if an Abort at this point in time might result in a corrupt +** database. +*/ +SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ + assert( p->nWrite==0 || p->usesStmtJournal ); +} +#endif + /* ** This routine is called after all opcodes have been inserted. It loops ** through all the opcodes and fixes up some details. @@ -72884,6 +75612,17 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){ } #endif +/* +** Generate code (a single OP_Abortable opcode) that will +** verify that the VDBE program can safely call Abort in the current +** context. +*/ +#if defined(SQLITE_DEBUG) +SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){ + if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable); +} +#endif + /* ** This function returns a pointer to the array of opcodes associated with ** the Vdbe passed as the first argument. It is the callers responsibility @@ -73050,6 +75789,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ case P4_REAL: case P4_INT64: case P4_DYNAMIC: + case P4_DYNBLOB: case P4_INTARRAY: { sqlite3DbFree(db, p4); break; @@ -73427,23 +76167,23 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){ const char *zOp = 0; switch( pExpr->op ){ case TK_STRING: - sqlite3XPrintf(p, "%Q", pExpr->u.zToken); + sqlite3_str_appendf(p, "%Q", pExpr->u.zToken); break; case TK_INTEGER: - sqlite3XPrintf(p, "%d", pExpr->u.iValue); + sqlite3_str_appendf(p, "%d", pExpr->u.iValue); break; case TK_NULL: - sqlite3XPrintf(p, "NULL"); + sqlite3_str_appendf(p, "NULL"); break; case TK_REGISTER: { - sqlite3XPrintf(p, "r[%d]", pExpr->iTable); + sqlite3_str_appendf(p, "r[%d]", pExpr->iTable); break; } case TK_COLUMN: { if( pExpr->iColumn<0 ){ - sqlite3XPrintf(p, "rowid"); + sqlite3_str_appendf(p, "rowid"); }else{ - sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); + sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn); } break; } @@ -73475,18 +76215,18 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){ case TK_NOTNULL: zOp = "NOTNULL"; break; default: - sqlite3XPrintf(p, "%s", "expr"); + sqlite3_str_appendf(p, "%s", "expr"); break; } if( zOp ){ - sqlite3XPrintf(p, "%s(", zOp); + sqlite3_str_appendf(p, "%s(", zOp); displayP4Expr(p, pExpr->pLeft); if( pExpr->pRight ){ - sqlite3StrAccumAppend(p, ",", 1); + sqlite3_str_append(p, ",", 1); displayP4Expr(p, pExpr->pRight); } - sqlite3StrAccumAppend(p, ")", 1); + sqlite3_str_append(p, ")", 1); } } #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ @@ -73507,14 +76247,15 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); - sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField); + sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); for(j=0; jnKeyField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : ""; if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; - sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); + sqlite3_str_appendf(&x, ",%s%s", + pKeyInfo->aSortOrder[j] ? "-" : "", zColl); } - sqlite3StrAccumAppend(&x, ")", 1); + sqlite3_str_append(&x, ")", 1); break; } #ifdef SQLITE_ENABLE_CURSOR_HINTS @@ -73525,31 +76266,31 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #endif case P4_COLLSEQ: { CollSeq *pColl = pOp->p4.pColl; - sqlite3XPrintf(&x, "(%.20s)", pColl->zName); + sqlite3_str_appendf(&x, "(%.20s)", pColl->zName); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; - sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; - sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #endif case P4_INT64: { - sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); + sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64); break; } case P4_INT32: { - sqlite3XPrintf(&x, "%d", pOp->p4.i); + sqlite3_str_appendf(&x, "%d", pOp->p4.i); break; } case P4_REAL: { - sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); + sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal); break; } case P4_MEM: { @@ -73557,9 +76298,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ if( pMem->flags & MEM_Str ){ zP4 = pMem->z; }else if( pMem->flags & MEM_Int ){ - sqlite3XPrintf(&x, "%lld", pMem->u.i); + sqlite3_str_appendf(&x, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ - sqlite3XPrintf(&x, "%.16g", pMem->u.r); + sqlite3_str_appendf(&x, "%.16g", pMem->u.r); }else if( pMem->flags & MEM_Null ){ zP4 = "NULL"; }else{ @@ -73571,7 +76312,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3XPrintf(&x, "vtab:%p", pVtab); + sqlite3_str_appendf(&x, "vtab:%p", pVtab); break; } #endif @@ -73581,22 +76322,23 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ int n = ai[0]; /* The first element of an INTARRAY is always the ** count of the number of elements to follow */ for(i=1; i<=n; i++){ - sqlite3XPrintf(&x, ",%d", ai[i]); + sqlite3_str_appendf(&x, ",%d", ai[i]); } zTemp[0] = '['; - sqlite3StrAccumAppend(&x, "]", 1); + sqlite3_str_append(&x, "]", 1); break; } case P4_SUBPROGRAM: { - sqlite3XPrintf(&x, "program"); + sqlite3_str_appendf(&x, "program"); break; } + case P4_DYNBLOB: case P4_ADVANCE: { zTemp[0] = 0; break; } case P4_TABLE: { - sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); + sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName); break; } default: { @@ -73808,6 +76550,9 @@ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ ** p->explain==2, only OP_Explain instructions are listed and these ** are shown in a different format. p->explain==2 is used to implement ** EXPLAIN QUERY PLAN. +** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers +** are also shown, so that the boundaries between the main program and +** each trigger are clear. ** ** When p->explain==1, first the main program is listed, then each of ** the trigger subprograms are listed one by one. @@ -73823,6 +76568,8 @@ SQLITE_PRIVATE int sqlite3VdbeList( int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ Mem *pMem = &p->aMem[1]; /* First Mem of result set */ + int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); + Op *pOp = 0; assert( p->explain ); assert( p->magic==VDBE_MAGIC_RUN ); @@ -73835,7 +76582,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( releaseMemArray(pMem, 8); p->pResultSet = 0; - if( p->rc==SQLITE_NOMEM_BKPT ){ + if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ sqlite3OomFault(db); @@ -73850,7 +76597,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( ** encountered, but p->pc will eventually catch up to nRow. */ nRow = p->nOp; - if( p->explain==1 ){ + if( bListSubprogs ){ /* The first 8 memory cells are used for the result set. So we will ** commandeer the 9th cell to use as storage for an array of pointers ** to trigger subprograms. The VDBE is guaranteed to have at least 9 @@ -73868,19 +76615,13 @@ SQLITE_PRIVATE int sqlite3VdbeList( } } - do{ + while(1){ /* Loop exits via break */ i = p->pc++; - }while( iexplain==2 && p->aOp[i].opcode!=OP_Explain ); - if( i>=nRow ){ - p->rc = SQLITE_OK; - rc = SQLITE_DONE; - }else if( db->u1.isInterrupted ){ - p->rc = SQLITE_INTERRUPT; - rc = SQLITE_ERROR; - sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); - }else{ - char *zP4; - Op *pOp; + if( i>=nRow ){ + p->rc = SQLITE_OK; + rc = SQLITE_DONE; + break; + } if( inOp ){ /* The output line number is small enough that we are still in the ** main program. */ @@ -73895,94 +76636,113 @@ SQLITE_PRIVATE int sqlite3VdbeList( } pOp = &apSub[j]->aOp[i]; } - if( p->explain==1 ){ - pMem->flags = MEM_Int; - pMem->u.i = i; /* Program counter */ - pMem++; - - pMem->flags = MEM_Static|MEM_Str|MEM_Term; - pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ - assert( pMem->z!=0 ); - pMem->n = sqlite3Strlen30(pMem->z); - pMem->enc = SQLITE_UTF8; - pMem++; - /* When an OP_Program opcode is encounter (the only opcode that has - ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms - ** kept in p->aMem[9].z to hold the new program - assuming this subprogram - ** has not already been seen. - */ - if( pOp->p4type==P4_SUBPROGRAM ){ - int nByte = (nSub+1)*sizeof(SubProgram*); - int j; - for(j=0; jp4.pProgram ) break; - } - if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ - apSub = (SubProgram **)pSub->z; - apSub[nSub++] = pOp->p4.pProgram; - pSub->flags |= MEM_Blob; - pSub->n = nSub*sizeof(SubProgram*); + /* When an OP_Program opcode is encounter (the only opcode that has + ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms + ** kept in p->aMem[9].z to hold the new program - assuming this subprogram + ** has not already been seen. + */ + if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){ + int nByte = (nSub+1)*sizeof(SubProgram*); + int j; + for(j=0; jp4.pProgram ) break; + } + if( j==nSub ){ + p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0); + if( p->rc!=SQLITE_OK ){ + rc = SQLITE_ERROR; + break; } + apSub = (SubProgram **)pSub->z; + apSub[nSub++] = pOp->p4.pProgram; + pSub->flags |= MEM_Blob; + pSub->n = nSub*sizeof(SubProgram*); + nRow += pOp->p4.pProgram->nOp; } } + if( p->explain<2 ) break; + if( pOp->opcode==OP_Explain ) break; + if( pOp->opcode==OP_Init && p->pc>1 ) break; + } - pMem->flags = MEM_Int; - pMem->u.i = pOp->p1; /* P1 */ - pMem++; - - pMem->flags = MEM_Int; - pMem->u.i = pOp->p2; /* P2 */ - pMem++; - - pMem->flags = MEM_Int; - pMem->u.i = pOp->p3; /* P3 */ - pMem++; - - if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ - assert( p->db->mallocFailed ); - return SQLITE_ERROR; - } - pMem->flags = MEM_Str|MEM_Term; - zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); - if( zP4!=pMem->z ){ - pMem->n = 0; - sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); + if( rc==SQLITE_OK ){ + if( db->u1.isInterrupted ){ + p->rc = SQLITE_INTERRUPT; + rc = SQLITE_ERROR; + sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); }else{ - assert( pMem->z!=0 ); - pMem->n = sqlite3Strlen30(pMem->z); - pMem->enc = SQLITE_UTF8; - } - pMem++; - - if( p->explain==1 ){ - if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ - assert( p->db->mallocFailed ); - return SQLITE_ERROR; + char *zP4; + if( p->explain==1 ){ + pMem->flags = MEM_Int; + pMem->u.i = i; /* Program counter */ + pMem++; + + pMem->flags = MEM_Static|MEM_Str|MEM_Term; + pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem++; } - pMem->flags = MEM_Str|MEM_Term; - pMem->n = 2; - sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ - pMem->enc = SQLITE_UTF8; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p1; /* P1 */ pMem++; - -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p2; /* P2 */ + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p3; /* P3 */ + pMem++; + + if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ assert( p->db->mallocFailed ); return SQLITE_ERROR; } pMem->flags = MEM_Str|MEM_Term; - pMem->n = displayComment(pOp, zP4, pMem->z, 500); - pMem->enc = SQLITE_UTF8; -#else - pMem->flags = MEM_Null; /* Comment */ -#endif - } + zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); + if( zP4!=pMem->z ){ + pMem->n = 0; + sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); + }else{ + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30(pMem->z); + pMem->enc = SQLITE_UTF8; + } + pMem++; - p->nResColumn = 8 - 4*(p->explain-1); - p->pResultSet = &p->aMem[1]; - p->rc = SQLITE_OK; - rc = SQLITE_ROW; + if( p->explain==1 ){ + if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + pMem->n = 2; + sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ + pMem->enc = SQLITE_UTF8; + pMem++; + +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + pMem->n = displayComment(pOp, zP4, pMem->z, 500); + pMem->enc = SQLITE_UTF8; +#else + pMem->flags = MEM_Null; /* Comment */ +#endif + } + + p->nResColumn = 8 - 4*(p->explain-1); + p->pResultSet = &p->aMem[1]; + p->rc = SQLITE_OK; + rc = SQLITE_ROW; + } } return rc; } @@ -74452,6 +77212,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ pPager = sqlite3BtreePager(pBt); if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF && aMJNeeded[sqlite3PagerGetJournalMode(pPager)] + && sqlite3PagerIsMemdb(pPager)==0 ){ assert( i!=1 ); nTrans++; @@ -75095,6 +77856,9 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; p->pResultSet = 0; +#ifdef SQLITE_DEBUG + p->nWrite = 0; +#endif /* Save profiling information from this VDBE run. */ @@ -75227,7 +77991,7 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; - if( NEVER(p==0) ) return; + assert( p!=0 ); db = p->db; assert( sqlite3_mutex_held(db->mutex) ); sqlite3VdbeClearObject(db, p); @@ -75623,7 +78387,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( Mem *pMem /* Memory cell to write value into */ ){ switch( serial_type ){ - case 10: /* Reserved for future use */ + case 10: { /* Internal use only: NULL with virtual table + ** UPDATE no-change flag set */ + pMem->flags = MEM_Null|MEM_Zero; + pMem->n = 0; + pMem->u.nZero = 0; + break; + } case 11: /* Reserved for future use */ case 0: { /* Null */ /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ @@ -76011,13 +78781,10 @@ static int sqlite3IntFloatCompare(i64 i, double r){ i64 y; double s; if( r<-9223372036854775808.0 ) return +1; - if( r>9223372036854775807.0 ) return -1; + if( r>=9223372036854775808.0 ) return -1; y = (i64)r; if( iy ){ - if( y==SMALLEST_INT64 && r>0.0 ) return -1; - return +1; - } + if( i>y ) return +1; s = (double)i; if( sr ) return +1; @@ -77176,6 +79943,11 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ return aType[pVal->flags&MEM_AffMask]; } +/* Return true if a parameter to xUpdate represents an unchanged column */ +SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){ + return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero); +} + /* Make a copy of an sqlite3_value object */ SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ @@ -77275,14 +80047,12 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif @@ -77388,8 +80158,7 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ return SQLITE_OK; } SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ - pCtx->isError = errCode; - pCtx->fErrorOrAux = 1; + pCtx->isError = errCode ? errCode : -1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif @@ -77403,7 +80172,6 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, SQLITE_UTF8, SQLITE_STATIC); } @@ -77413,7 +80181,6 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; - pCtx->fErrorOrAux = 1; sqlite3OomFault(pCtx->pOut->db); } @@ -77653,6 +80420,25 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ return p->pOut->db; } +/* +** If this routine is invoked from within an xColumn method of a virtual +** table, then it returns true if and only if the the call is during an +** UPDATE operation and the value of the column will not be modified +** by the UPDATE. +** +** If this routine is called from any context other than within the +** xColumn method of a virtual table, then the return value is meaningless +** and arbitrary. +** +** Virtual table implements might use this routine to optimize their +** performance by substituting a NULL result, or some other light-weight +** value, as a signal to the xUpdate routine that the column is unchanged. +*/ +SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ + assert( p ); + return sqlite3_value_nochange(p->pOut); +} + /* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared @@ -77676,28 +80462,6 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ return *piTime; } -/* -** The following is the implementation of an SQL function that always -** fails with an error message stating that the function is used in the -** wrong context. The sqlite3_overload_function() API might construct -** SQL function that use this routine so that the functions will exist -** for name resolution but are actually overloaded by the xFindFunction -** method of virtual tables. -*/ -SQLITE_PRIVATE void sqlite3InvalidFunction( - sqlite3_context *context, /* The function calling context */ - int NotUsed, /* Number of arguments to the function */ - sqlite3_value **NotUsed2 /* Value of each argument */ -){ - const char *zName = context->pFunc->zName; - char *zErr; - UNUSED_PARAMETER2(NotUsed, NotUsed2); - zErr = sqlite3_mprintf( - "unable to use function %s in the requested context", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); -} - /* ** Create a new aggregate context for p and return a pointer to ** its pMem->z element. @@ -77801,10 +80565,7 @@ SQLITE_API void sqlite3_set_auxdata( pAuxData->iAuxArg = iArg; pAuxData->pNextAux = pVdbe->pAuxData; pVdbe->pAuxData = pAuxData; - if( pCtx->fErrorOrAux==0 ){ - pCtx->isError = 0; - pCtx->fErrorOrAux = 1; - } + if( pCtx->isError==0 ) pCtx->isError = -1; }else if( pAuxData->xDeleteAux ){ pAuxData->xDeleteAux(pAuxData->pAux); } @@ -78560,7 +81321,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR - if( !pStmt ){ + if( !pStmt + || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) + ){ (void)SQLITE_MISUSE_BKPT; return 0; } @@ -78966,17 +81729,17 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( while( *zRawSql ){ const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); - sqlite3StrAccumAppend(&out, "-- ", 3); + sqlite3_str_append(&out, "-- ", 3); assert( (zRawSql - zStart) > 0 ); - sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); + sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart)); } }else if( p->nVar==0 ){ - sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); + sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql)); }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); assert( n>0 ); - sqlite3StrAccumAppend(&out, zRawSql, n); + sqlite3_str_append(&out, zRawSql, n); zRawSql += n; assert( zRawSql[0] || nToken==0 ); if( nToken==0 ) break; @@ -79002,11 +81765,11 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( assert( idx>0 && idx<=p->nVar ); pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ - sqlite3StrAccumAppend(&out, "NULL", 4); + sqlite3_str_append(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ - sqlite3XPrintf(&out, "%lld", pVar->u.i); + sqlite3_str_appendf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, "%!.15g", pVar->u.r); + sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 @@ -79016,7 +81779,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( utf8.db = db; sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ - out.accError = STRACCUM_NOMEM; + out.accError = SQLITE_NOMEM; out.nAlloc = 0; } pVar = &utf8; @@ -79029,38 +81792,38 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } } #endif - sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); + sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); + sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); #endif }else if( pVar->flags & MEM_Zero ){ - sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); + sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero); }else{ int nOut; /* Number of bytes of the blob to include in output */ assert( pVar->flags & MEM_Blob ); - sqlite3StrAccumAppend(&out, "x'", 2); + sqlite3_str_append(&out, "x'", 2); nOut = pVar->n; #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; #endif for(i=0; iz[i]&0xff); + sqlite3_str_appendf(&out, "%02x", pVar->z[i]&0xff); } - sqlite3StrAccumAppend(&out, "'", 1); + sqlite3_str_append(&out, "'", 1); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); + sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif } } } - if( out.accError ) sqlite3StrAccumReset(&out); + if( out.accError ) sqlite3_str_reset(&out); return sqlite3StrAccumFinish(&out); } @@ -79334,6 +82097,11 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ pRec->flags |= MEM_Real; if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } + /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the + ** string representation after computing a numeric equivalent, because the + ** string representation might not be the canonical representation for the + ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */ + pRec->flags &= ~MEM_Str; } /* @@ -79534,7 +82302,7 @@ static void memTracePrint(Mem *p){ if( p->flags & MEM_Undefined ){ printf(" undefined"); }else if( p->flags & MEM_Null ){ - printf(" NULL"); + printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ printf(" si:%lld", p->u.i); }else if( p->flags & MEM_Int ){ @@ -79802,7 +82570,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( pOp>=aOp && pOp<&aOp[p->nOp]); #ifdef VDBE_PROFILE - start = sqlite3Hwtime(); + start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); #endif nVmStep++; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS @@ -80069,6 +82837,9 @@ case OP_Yield: { /* in1, jump */ */ case OP_HaltIfNull: { /* in3 */ pIn3 = &aMem[pOp->p3]; +#ifdef SQLITE_DEBUG + if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } +#endif if( (pIn3->flags & MEM_Null)==0 ) break; /* Fall through into OP_Halt */ } @@ -80108,6 +82879,9 @@ case OP_Halt: { int pcx; pcx = (int)(pOp - aOp); +#ifdef SQLITE_DEBUG + if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } +#endif if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ pFrame = p->pFrame; @@ -81326,18 +84100,8 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - v1 = 2; - }else{ - v1 = sqlite3VdbeIntValue(pIn1)!=0; - } - pIn2 = &aMem[pOp->p2]; - if( pIn2->flags & MEM_Null ){ - v2 = 2; - }else{ - v2 = sqlite3VdbeIntValue(pIn2)!=0; - } + v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2); + v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2); if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = and_logic[v1*3+v2]; @@ -81355,6 +84119,35 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ break; } +/* Opcode: IsTrue P1 P2 P3 P4 * +** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 +** +** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and +** IS NOT FALSE operators. +** +** Interpret the value in register P1 as a boolean value. Store that +** boolean (a 0 or 1) in register P2. Or if the value in register P1 is +** NULL, then the P3 is stored in register P2. Invert the answer if P4 +** is 1. +** +** The logic is summarized like this: +** +**
      +**
    • If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE +**
    • If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE +**
    • If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE +**
    • If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE +**
    +*/ +case OP_IsTrue: { /* in1, out2 */ + assert( pOp->p4type==P4_INT32 ); + assert( pOp->p4.i==0 || pOp->p4.i==1 ); + assert( pOp->p3==0 || pOp->p3==1 ); + sqlite3VdbeMemSetInt64(&aMem[pOp->p2], + sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); + break; +} + /* Opcode: Not P1 P2 * * * ** Synopsis: r[P2]= !r[P1] ** @@ -81365,10 +84158,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ case OP_Not: { /* same as TK_NOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); if( (pIn1->flags & MEM_Null)==0 ){ - pOut->flags = MEM_Int; - pOut->u.i = !sqlite3VdbeIntValue(pIn1); + sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0)); + }else{ + sqlite3VdbeMemSetNull(pOut); } break; } @@ -81435,30 +84228,25 @@ case OP_Once: { /* jump */ ** is considered true if it is numeric and non-zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ +case OP_If: { /* jump, in1 */ + int c; + c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3); + VdbeBranchTaken(c!=0, 2); + if( c ) goto jump_to_p2; + break; +} + /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered false if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ -case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - c = pOp->p3; - }else{ -#ifdef SQLITE_OMIT_FLOATING_POINT - c = sqlite3VdbeIntValue(pIn1)!=0; -#else - c = sqlite3VdbeRealValue(pIn1)!=0.0; -#endif - if( pOp->opcode==OP_IfNot ) c = !c; - } + c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3); VdbeBranchTaken(c!=0, 2); - if( c ){ - goto jump_to_p2; - } + if( c ) goto jump_to_p2; break; } @@ -81508,6 +84296,36 @@ case OP_IfNullRow: { /* jump */ break; } +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +/* Opcode: Offset P1 P2 P3 * * +** Synopsis: r[P3] = sqlite_offset(P1) +** +** Store in register r[P3] the byte offset into the database file that is the +** start of the payload for the record at which that cursor P1 is currently +** pointing. +** +** P2 is the column number for the argument to the sqlite_offset() function. +** This opcode does not use P2 itself, but the P2 value is used by the +** code generator. The P1, P2, and P3 operands to this opcode are the +** same as for OP_Column. +** +** This opcode is only available if SQLite is compiled with the +** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. +*/ +case OP_Offset: { /* out3 */ + VdbeCursor *pC; /* The VDBE cursor */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + pOut = &p->aMem[pOp->p3]; + if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){ + sqlite3VdbeMemSetNull(pOut); + }else{ + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); + } + break; +} +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ + /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX ** @@ -81921,9 +84739,18 @@ case OP_MakeRecord: { pRec = pLast; do{ assert( memIsValid(pRec) ); - pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); + serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); if( pRec->flags & MEM_Zero ){ - if( nData ){ + if( serial_type==0 ){ + /* Values with MEM_Null and MEM_Zero are created by xColumn virtual + ** table methods that never invoke sqlite3_result_xxxxx() while + ** computing an unchanging column value in an UPDATE statement. + ** Give such values a special internal-use-only serial-type of 10 + ** so that they can be passed through to xUpdate and have + ** a true sqlite3_value_nochange(). */ + assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); + serial_type = 10; + }else if( nData ){ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ nZero += pRec->u.nZero; @@ -81934,6 +84761,7 @@ case OP_MakeRecord: { testcase( serial_type==127 ); testcase( serial_type==128 ); nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); + pRec->uTemp = serial_type; if( pRec==pData0 ) break; pRec--; }while(1); @@ -82424,6 +85252,8 @@ case OP_ReadCookie: { /* out2 */ */ case OP_SetCookie: { Db *pDb; + + sqlite3VdbeIncrWriteCounter(p, 0); assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); @@ -83388,6 +86218,7 @@ case OP_NewRowid: { /* out2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); + assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); { @@ -83544,10 +86375,8 @@ case OP_InsertInt: { int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ const char *zDb; /* database name - used by the update hook */ Table *pTab; /* Table structure - used by update and pre-update hooks */ - int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ BtreePayload x; /* Payload to be inserted */ - op = 0; pData = &aMem[pOp->p2]; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( memIsValid(pData) ); @@ -83558,6 +86387,7 @@ case OP_InsertInt: { assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); REGISTER_TRACE(pOp->p2, pData); + sqlite3VdbeIncrWriteCounter(p, pC); if( pOp->opcode==OP_Insert ){ pKey = &aMem[pOp->p3]; @@ -83575,19 +86405,21 @@ case OP_InsertInt: { zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) ); - op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); }else{ - pTab = 0; /* Not needed. Silence a compiler warning. */ + pTab = 0; zDb = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update hook, if any */ - if( db->xPreUpdateCallback - && pOp->p4type==P4_TABLE - && !(pOp->p5 & OPFLAG_ISUPDATE) - ){ - sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2); + if( pTab ){ + if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){ + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2); + } + if( db->xUpdateCallback==0 || pTab->aCol==0 ){ + /* Prevent post-update hook from running in cases when it should not */ + pTab = 0; + } } if( pOp->p5 & OPFLAG_ISNOOP ) break; #endif @@ -83612,8 +86444,12 @@ case OP_InsertInt: { /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; - if( db->xUpdateCallback && op ){ - db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey); + if( pTab ){ + assert( db->xUpdateCallback!=0 ); + assert( pTab->aCol!=0 ); + db->xUpdateCallback(db->pUpdateArg, + (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT, + zDb, pTab->zName, x.nKey); } break; } @@ -83666,6 +86502,7 @@ case OP_Delete: { assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->deferredMoveto==0 ); + sqlite3VdbeIncrWriteCounter(p, pC); #ifdef SQLITE_DEBUG if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ @@ -83834,10 +86671,10 @@ case OP_SorterData: { ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. ** -** If P3!=0 then this opcode is allowed to make an ephermeral pointer +** If P3!=0 then this opcode is allowed to make an ephemeral pointer ** into the database page. That means that the content of the output ** register will be invalidated as soon as the cursor moves - including -** moves caused by other cursors that "save" the the current cursors +** moves caused by other cursors that "save" the current cursors ** position in order that they can write to the same table. If P3==0 ** then a copy of the data is made into memory. P3!=0 is faster, but ** P3==0 is safer. @@ -84284,6 +87121,7 @@ case OP_IdxInsert: { /* in2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; + sqlite3VdbeIncrWriteCounter(p, pC); assert( pC!=0 ); assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; @@ -84330,6 +87168,7 @@ case OP_IdxDelete: { pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); + sqlite3VdbeIncrWriteCounter(p, pC); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); assert( pOp->p5==0 ); @@ -84552,6 +87391,7 @@ case OP_Destroy: { /* out2 */ int iMoved; int iDb; + sqlite3VdbeIncrWriteCounter(p, 0); assert( p->readOnly==0 ); assert( pOp->p1>1 ); pOut = out2Prerelease(p, pOp); @@ -84601,6 +87441,7 @@ case OP_Destroy: { /* out2 */ case OP_Clear: { int nChange; + sqlite3VdbeIncrWriteCounter(p, 0); nChange = 0; assert( p->readOnly==0 ); assert( DbMaskTest(p->btreeMask, pOp->p2) ); @@ -84650,13 +87491,14 @@ case OP_ResetSorter: { ** Allocate a new b-tree in the main database file if P1==0 or in the ** TEMP database file if P1==1 or in an attached database if ** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table -** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table. +** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table. ** The root page number of the new b-tree is stored in register P2. */ case OP_CreateBtree: { /* out2 */ int pgno; Db *pDb; + sqlite3VdbeIncrWriteCounter(p, 0); pOut = out2Prerelease(p, pOp); pgno = 0; assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY ); @@ -84676,6 +87518,7 @@ case OP_CreateBtree: { /* out2 */ ** Run the SQL statement or statements specified in the P4 string. */ case OP_SqlExec: { + sqlite3VdbeIncrWriteCounter(p, 0); db->nSqlExec++; rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); db->nSqlExec--; @@ -84765,6 +87608,7 @@ case OP_LoadAnalysis: { ** schema consistent with what is on disk. */ case OP_DropTable: { + sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); break; } @@ -84778,6 +87622,7 @@ case OP_DropTable: { ** schema consistent with what is on disk. */ case OP_DropIndex: { + sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); break; } @@ -84791,6 +87636,7 @@ case OP_DropIndex: { ** schema consistent with what is on disk. */ case OP_DropTrigger: { + sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); break; } @@ -85319,12 +88165,17 @@ case OP_AggStep0: { assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) + + (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*))); if( pCtx==0 ) goto no_mem; pCtx->pMem = 0; + pCtx->pOut = (Mem*)&(pCtx->argv[n]); + sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; + pCtx->skipFlag = 0; + pCtx->isError = 0; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; @@ -85335,7 +88186,6 @@ case OP_AggStep: { int i; sqlite3_context *pCtx; Mem *pMem; - Mem t; assert( pOp->p4type==P4_FUNCCTX ); pCtx = pOp->p4.pCtx; @@ -85358,26 +88208,28 @@ case OP_AggStep: { #endif pMem->n++; - sqlite3VdbeMemInit(&t, db, MEM_Null); - pCtx->pOut = &t; - pCtx->fErrorOrAux = 0; - pCtx->skipFlag = 0; + assert( pCtx->pOut->flags==MEM_Null ); + assert( pCtx->isError==0 ); + assert( pCtx->skipFlag==0 ); (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); + if( pCtx->isError ){ + if( pCtx->isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } - sqlite3VdbeMemRelease(&t); + if( pCtx->skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); + pCtx->skipFlag = 0; + } + sqlite3VdbeMemRelease(pCtx->pOut); + pCtx->pOut->flags = MEM_Null; + pCtx->isError = 0; if( rc ) goto abort_due_to_error; - }else{ - assert( t.flags==MEM_Null ); - } - if( pCtx->skipFlag ){ - assert( pOp[-1].opcode==OP_CollSeq ); - i = pOp[-1].p1; - if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } + assert( pCtx->pOut->flags==MEM_Null ); + assert( pCtx->skipFlag==0 ); break; } @@ -85822,12 +88674,18 @@ case OP_VFilter: { /* jump */ #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VColumn P1 P2 P3 * * +/* Opcode: VColumn P1 P2 P3 * P5 ** Synopsis: r[P3]=vcolumn(P2) ** -** Store the value of the P2-th column of -** the row of the virtual-table that the -** P1 cursor is pointing to into register P3. +** Store in register P3 the value of the P2-th column of +** the current row of the virtual-table of cursor P1. +** +** If the VColumn opcode is being used to fetch the value of +** an unchanging column during an UPDATE operation, then the P5 +** value is 1. Otherwise, P5 is 0. The P5 value is returned +** by sqlite3_vtab_nochange() routine and can be used +** by virtual table implementations to return special "no-change" +** marks which can be more efficient, depending on the virtual table. */ case OP_VColumn: { sqlite3_vtab *pVtab; @@ -85849,10 +88707,17 @@ case OP_VColumn: { assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); sContext.pOut = pDest; - MemSetTypeFlag(pDest, MEM_Null); + if( pOp->p5 ){ + sqlite3VdbeMemSetNull(pDest); + pDest->flags = MEM_Null|MEM_Zero; + pDest->u.nZero = 0; + }else{ + MemSetTypeFlag(pDest, MEM_Null); + } rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); sqlite3VtabImportErrmsg(p, pVtab); - if( sContext.isError ){ + if( sContext.isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest)); rc = sContext.isError; } sqlite3VdbeChangeEncoding(pDest, encoding); @@ -85981,6 +88846,7 @@ case OP_VUpdate: { || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); assert( p->readOnly==0 ); + sqlite3VdbeIncrWriteCounter(p, 0); pVtab = pOp->p4.pVtab->pVtab; if( pVtab==0 || NEVER(pVtab->pModule==0) ){ rc = SQLITE_LOCKED; @@ -86117,6 +88983,7 @@ case OP_Function0: { pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; + pCtx->isError = 0; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; @@ -86151,16 +89018,17 @@ case OP_Function: { } #endif MemSetTypeFlag(pOut, MEM_Null); - pCtx->fErrorOrAux = 0; + assert( pCtx->isError==0 ); (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ /* If the function returned an error, throw an exception */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ + if( pCtx->isError ){ + if( pCtx->isError>0 ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); rc = pCtx->isError; } sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); + pCtx->isError = 0; if( rc ) goto abort_due_to_error; } @@ -86175,7 +89043,13 @@ case OP_Function: { break; } - +/* Opcode: Trace P1 P2 * P4 * +** +** Write P4 on the statement trace output if statement tracing is +** enabled. +** +** Operand P1 must be 0x7fffffff and P2 must positive. +*/ /* Opcode: Init P1 P2 P3 P4 * ** Synopsis: Start at P2 ** @@ -86194,9 +89068,12 @@ case OP_Function: { ** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT ** error is encountered. */ +case OP_Trace: case OP_Init: { /* jump */ - char *zTrace; int i; +#ifndef SQLITE_OMIT_TRACE + char *zTrace; +#endif /* If the P4 argument is not NULL, then it must be an SQL comment string. ** The "--" string is broken up to prevent false-positives with srcck1.c. @@ -86208,7 +89085,9 @@ case OP_Init: { /* jump */ ** sqlite3_expanded_sql(P) otherwise. */ assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); - assert( pOp==p->aOp ); /* Always instruction 0 */ + + /* OP_Init is always instruction 0 */ + assert( pOp==p->aOp || pOp->opcode==OP_Trace ); #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 @@ -86251,6 +89130,7 @@ case OP_Init: { /* jump */ #endif /* SQLITE_OMIT_TRACE */ assert( pOp->p2>0 ); if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ + if( pOp->opcode==OP_Trace ) break; for(i=1; inOp; i++){ if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; } @@ -86284,6 +89164,22 @@ case OP_CursorHint: { } #endif /* SQLITE_ENABLE_CURSOR_HINTS */ +#ifdef SQLITE_DEBUG +/* Opcode: Abortable * * * * * +** +** Verify that an Abort can happen. Assert if an Abort at this point +** might cause database corruption. This opcode only appears in debugging +** builds. +** +** An Abort is safe if either there have been no writes, or if there is +** an active statement journal. +*/ +case OP_Abortable: { + sqlite3VdbeAssertAbortable(p); + break; +} +#endif + /* Opcode: Noop * * * * * ** ** Do nothing. This instruction is often useful as a jump @@ -86295,8 +89191,9 @@ case OP_CursorHint: { ** This opcode records information from the optimizer. It is the ** the same as a no-op. This opcodesnever appears in a real VM program. */ -default: { /* This is really OP_Noop and OP_Explain */ +default: { /* This is really OP_Noop, OP_Explain */ assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); + break; } @@ -86310,7 +89207,7 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { - u64 endTime = sqlite3Hwtime(); + u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); if( endTime>start ) pOrigOp->cycles += endTime - start; pOrigOp->cnt++; } @@ -90195,7 +93092,6 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){ if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort; return WRC_Continue; } @@ -90212,16 +93108,15 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ struct SrcList_item *pItem; pSrc = p->pSrc; - if( ALWAYS(pSrc) ){ - for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ - return WRC_Abort; - } - if( pItem->fg.isTabFunc - && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } + assert( pSrc!=0 ); + for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ + if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ + return WRC_Abort; + } + if( pItem->fg.isTabFunc + && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) + ){ + return WRC_Abort; } } return WRC_Continue; @@ -90343,29 +93238,31 @@ static void resolveAlias( assert( pOrig!=0 ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); - if( pDup==0 ) return; - if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); - if( pExpr->op==TK_COLLATE ){ - pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); - } - ExprSetProperty(pDup, EP_Alias); + if( pDup!=0 ){ + if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); + if( pExpr->op==TK_COLLATE ){ + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); + } + ExprSetProperty(pDup, EP_Alias); - /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This - ** prevents ExprDelete() from deleting the Expr structure itself, - ** allowing it to be repopulated by the memcpy() on the following line. - ** The pExpr->u.zToken might point into memory that will be freed by the - ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to - ** make a copy of the token before doing the sqlite3DbFree(). - */ - ExprSetProperty(pExpr, EP_Static); - sqlite3ExprDelete(db, pExpr); - memcpy(pExpr, pDup, sizeof(*pExpr)); - if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ - assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); - pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); - pExpr->flags |= EP_MemToken; + /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This + ** prevents ExprDelete() from deleting the Expr structure itself, + ** allowing it to be repopulated by the memcpy() on the following line. + ** The pExpr->u.zToken might point into memory that will be freed by the + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to + ** make a copy of the token before doing the sqlite3DbFree(). + */ + ExprSetProperty(pExpr, EP_Static); + sqlite3ExprDelete(db, pExpr); + memcpy(pExpr, pDup, sizeof(*pExpr)); + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); + pExpr->flags |= EP_MemToken; + } + sqlite3DbFree(db, pDup); } - sqlite3DbFree(db, pDup); + ExprSetProperty(pExpr, EP_Alias); } @@ -90459,7 +93356,7 @@ static int lookupName( struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ - int isTrigger = 0; /* True if resolved to a trigger column */ + int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ @@ -90564,22 +93461,35 @@ static int lookupName( } } /* if( pSrcList ) */ -#ifndef SQLITE_OMIT_TRIGGER +#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) /* If we have not already resolved the name, then maybe - ** it is a new.* or old.* trigger argument reference + ** it is a new.* or old.* trigger argument reference. Or + ** maybe it is an excluded.* from an upsert. */ - if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){ - int op = pParse->eTriggerOp; - assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); - if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ - pExpr->iTable = 1; - pTab = pParse->pTriggerTab; - }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ - pExpr->iTable = 0; - pTab = pParse->pTriggerTab; - }else{ - pTab = 0; + if( zDb==0 && zTab!=0 && cntTab==0 ){ + pTab = 0; +#ifndef SQLITE_OMIT_TRIGGER + if( pParse->pTriggerTab!=0 ){ + int op = pParse->eTriggerOp; + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); + if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ + pExpr->iTable = 1; + pTab = pParse->pTriggerTab; + }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ + pExpr->iTable = 0; + pTab = pParse->pTriggerTab; + } } +#endif /* SQLITE_OMIT_TRIGGER */ +#ifndef SQLITE_OMIT_UPSERT + if( (pNC->ncFlags & NC_UUpsert)!=0 ){ + Upsert *pUpsert = pNC->uNC.pUpsert; + if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){ + pTab = pUpsert->pUpsertSrc->a[0].pTab; + pExpr->iTable = 2; + } + } +#endif /* SQLITE_OMIT_UPSERT */ if( pTab ){ int iCol; @@ -90599,24 +93509,36 @@ static int lookupName( } if( iColnCol ){ cnt++; - if( iCol<0 ){ - pExpr->affinity = SQLITE_AFF_INTEGER; - }else if( pExpr->iTable==0 ){ - testcase( iCol==31 ); - testcase( iCol==32 ); - pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<iTable==2 ){ + testcase( iCol==(-1) ); + pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; + eNewExprOp = TK_REGISTER; + ExprSetProperty(pExpr, EP_Alias); + }else +#endif /* SQLITE_OMIT_UPSERT */ + { +#ifndef SQLITE_OMIT_TRIGGER + if( iCol<0 ){ + pExpr->affinity = SQLITE_AFF_INTEGER; + }else if( pExpr->iTable==0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); + pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<pTab = pTab; + pExpr->iColumn = (i16)iCol; + eNewExprOp = TK_TRIGGER; +#endif /* SQLITE_OMIT_TRIGGER */ } - pExpr->iColumn = (i16)iCol; - pExpr->pTab = pTab; - isTrigger = 1; } } } -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ +#endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ /* ** Perhaps the name is a reference to the ROWID @@ -90651,10 +93573,12 @@ static int lookupName( ** is supported for backwards compatibility only. Hence, we issue a warning ** on sqlite3_log() whenever the capability is used. */ - if( (pEList = pNC->pEList)!=0 - && zTab==0 + if( (pNC->ncFlags & NC_UEList)!=0 && cnt==0 + && zTab==0 ){ + pEList = pNC->uNC.pEList; + assert( pEList!=0 ); for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ @@ -90699,10 +93623,16 @@ static int lookupName( ** Because no reference was made to outer contexts, the pNC->nRef ** fields are not changed in any context. */ - if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ - pExpr->op = TK_STRING; - pExpr->pTab = 0; - return WRC_Prune; + if( cnt==0 && zTab==0 ){ + assert( pExpr->op==TK_ID ); + if( ExprHasProperty(pExpr,EP_DblQuoted) ){ + pExpr->op = TK_STRING; + pExpr->pTab = 0; + return WRC_Prune; + } + if( sqlite3ExprIdToTrueFalse(pExpr) ){ + return WRC_Prune; + } } /* @@ -90745,7 +93675,7 @@ static int lookupName( pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; - pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); + pExpr->op = eNewExprOp; ExprSetProperty(pExpr, EP_Leaf); lookupname_end: if( cnt==1 ){ @@ -90864,7 +93794,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ SrcList *pSrcList = pNC->pSrcList; struct SrcList_item *pItem; assert( pSrcList && pSrcList->nSrc==1 ); - pItem = pSrcList->a; + pItem = pSrcList->a; + assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); pExpr->op = TK_COLUMN; pExpr->pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; @@ -91050,15 +93981,30 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + case TK_IS: + case TK_ISNOT: { + Expr *pRight; + assert( !ExprHasProperty(pExpr, EP_Reduced) ); + /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", + ** and "x IS NOT FALSE". */ + if( (pRight = pExpr->pRight)->op==TK_ID ){ + int rc = resolveExprStep(pWalker, pRight); + if( rc==WRC_Abort ) return WRC_Abort; + if( pRight->op==TK_TRUEFALSE ){ + pExpr->op2 = pExpr->op; + pExpr->op = TK_TRUTH; + return WRC_Continue; + } + } + /* Fall thru */ + } case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: - case TK_GE: - case TK_IS: - case TK_ISNOT: { + case TK_GE: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; assert( pExpr->pLeft!=0 ); @@ -91161,8 +94107,8 @@ static int resolveOrderByTermToExprList( memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; - nc.pEList = pEList; - nc.ncFlags = NC_AllowAgg; + nc.uNC.pEList = pEList; + nc.ncFlags = NC_AllowAgg|NC_UEList; nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; @@ -91463,8 +94409,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; - if( sqlite3ResolveExprNames(&sNC, p->pLimit) || - sqlite3ResolveExprNames(&sNC, p->pOffset) ){ + if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ return WRC_Abort; } @@ -91546,7 +94491,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ - sNC.pEList = p->pEList; + assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 ); + sNC.uNC.pEList = p->pEList; + sNC.ncFlags |= NC_UEList; if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; @@ -91779,7 +94726,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( Table *pTab, /* The table being referenced */ int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ Expr *pExpr, /* Expression to resolve. May be NULL. */ - ExprList *pList /* Expression list to resolve. May be NUL. */ + ExprList *pList /* Expression list to resolve. May be NULL. */ ){ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ @@ -92460,16 +95407,15 @@ static void heightOfExprList(ExprList *p, int *pnHeight){ } } } -static void heightOfSelect(Select *p, int *pnHeight){ - if( p ){ +static void heightOfSelect(Select *pSelect, int *pnHeight){ + Select *p; + for(p=pSelect; p; p=p->pPrior){ heightOfExpr(p->pWhere, pnHeight); heightOfExpr(p->pHaving, pnHeight); heightOfExpr(p->pLimit, pnHeight); - heightOfExpr(p->pOffset, pnHeight); heightOfExprList(p->pEList, pnHeight); heightOfExprList(p->pGroupBy, pnHeight); heightOfExprList(p->pOrderBy, pnHeight); - heightOfSelect(p->pPrior, pnHeight); } } @@ -92754,6 +95700,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * return 0; } pNew->x.pList = pList; + ExprSetProperty(pNew, EP_HasFunc); assert( !ExprHasProperty(pNew, EP_xIsSelect) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); return pNew; @@ -93165,6 +96112,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags) pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->bSpanIsTab = pOldItem->bSpanIsTab; + pItem->bSorterRef = pOldItem->bSorterRef; pItem->u = pOldItem->u; } return pNew; @@ -93263,7 +96211,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ pNew->pNext = pNext; pNew->pPrior = 0; pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); - pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; @@ -93457,17 +96404,16 @@ SQLITE_PRIVATE void sqlite3ExprListSetName( SQLITE_PRIVATE void sqlite3ExprListSetSpan( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to add the span. */ - ExprSpan *pSpan /* The span to be added */ + const char *zStart, /* Start of the span */ + const char *zEnd /* End of the span */ ){ sqlite3 *db = pParse->db; assert( pList!=0 || db->mallocFailed!=0 ); if( pList ){ struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; assert( pList->nExpr>0 ); - assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); sqlite3DbFree(db, pItem->zSpan); - pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); + pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd); } } @@ -93536,6 +96482,34 @@ SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){ return WRC_Abort; } +/* +** If the input expression is an ID with the name "true" or "false" +** then convert it into an TK_TRUEFALSE term. Return non-zero if +** the conversion happened, and zero if the expression is unaltered. +*/ +SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ + assert( pExpr->op==TK_ID || pExpr->op==TK_STRING ); + if( sqlite3StrICmp(pExpr->u.zToken, "true")==0 + || sqlite3StrICmp(pExpr->u.zToken, "false")==0 + ){ + pExpr->op = TK_TRUEFALSE; + return 1; + } + return 0; +} + +/* +** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE +** and 0 if it is FALSE. +*/ +SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ + assert( pExpr->op==TK_TRUEFALSE ); + assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 + || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); + return pExpr->u.zToken[4]==0; +} + + /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The @@ -93583,6 +96557,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Abort; } case TK_ID: + /* Convert "true" or "false" in a DEFAULT clause into the + ** appropriate TK_TRUEFALSE operator */ + if( sqlite3ExprIdToTrueFalse(pExpr) ){ + return WRC_Prune; + } + /* Fall thru */ case TK_COLUMN: case TK_AGG_FUNCTION: case TK_AGG_COLUMN: @@ -93595,6 +96575,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ } /* Fall through */ case TK_IF_NULL_ROW: + case TK_REGISTER: + testcase( pExpr->op==TK_REGISTER ); testcase( pExpr->op==TK_IF_NULL_ROW ); pWalker->eCode = 0; return WRC_Abort; @@ -93612,8 +96594,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ } /* Fall through */ default: - testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */ - testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */ + testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ + testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ return WRC_Continue; } } @@ -93900,7 +96882,6 @@ static Select *isCandidateForInOpt(Expr *pX){ } assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ if( p->pLimit ) return 0; /* Has no LIMIT clause */ - assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */ if( p->pWhere ) return 0; /* Has no WHERE clause */ pSrc = p->pSrc; assert( pSrc!=0 ); @@ -93990,16 +96971,15 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** pX->iTable made to point to the ephemeral table instead of an ** existing table. ** -** The inFlags parameter must contain exactly one of the bits -** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains -** IN_INDEX_MEMBERSHIP, then the generated table will be used for a -** fast membership test. When the IN_INDEX_LOOP bit is set, the -** IN index will be used to loop over all values of the RHS of the -** IN operator. +** The inFlags parameter must contain, at a minimum, one of the bits +** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains +** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast +** membership test. When the IN_INDEX_LOOP bit is set, the IN index will +** be used to loop over all values of the RHS of the IN operator. ** ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate ** through the set members) then the b-tree must not contain duplicates. -** An epheremal table must be used unless the selected columns are guaranteed +** An epheremal table will be created unless the selected columns are guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or due to ** a UNIQUE constraint or index. ** @@ -94179,11 +97159,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex( if( colUsed==(MASKBIT(nExpr)-1) ){ /* If we reach this point, that means the index pIdx is usable */ int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); -#ifndef SQLITE_OMIT_EXPLAIN - sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, - sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), - P4_DYNAMIC); -#endif + ExplainQueryPlan((pParse, 0, + "USING INDEX %s FOR IN-OPERATOR",pIdx->zName)); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); @@ -94378,17 +97355,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } -#ifndef SQLITE_OMIT_EXPLAIN - if( pParse->explain==2 ){ - char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", - jmpIfDynamic>=0?"":"CORRELATED ", - pExpr->op==TK_IN?"LIST":"SCALAR", - pParse->iNextSelectId - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } -#endif - switch( pExpr->op ){ case TK_IN: { int addr; /* Address of OP_OpenEphemeral instruction */ @@ -94426,6 +97392,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( Select *pSelect = pExpr->x.pSelect; ExprList *pEList = pSelect->pEList; + ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY", + jmpIfDynamic>=0?"":"CORRELATED " + )); assert( !isRowid ); /* If the LHS and RHS of the IN operator do not match, that ** error will have been caught long before we reach this point. */ @@ -94467,7 +97436,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; - affinity = sqlite3ExprAffinity(pLeft); if( !affinity ){ affinity = SQLITE_AFF_BLOB; @@ -94540,6 +97508,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( Select *pSel; /* SELECT statement to encode */ SelectDest dest; /* How to deal with SELECT result */ int nReg; /* Registers to allocate */ + Expr *pLimit; /* New limit expression */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); @@ -94547,6 +97516,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( assert( ExprHasProperty(pExpr, EP_xIsSelect) ); pSel = pExpr->x.pSelect; + ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", + jmpIfDynamic>=0?"":"CORRELATED ")); nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); pParse->nMem += nReg; @@ -94561,11 +97532,14 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); VdbeComment((v, "Init EXISTS result")); } - sqlite3ExprDelete(pParse->db, pSel->pLimit); - pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, - &sqlite3IntTokens[1], 0); + pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0); + if( pSel->pLimit ){ + sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft); + pSel->pLimit->pLeft = pLimit; + }else{ + pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); + } pSel->iLimit = 0; - pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } @@ -95306,6 +98280,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) return 0; } +expr_code_doover: if( pExpr==0 ){ op = TK_NULL; }else{ @@ -95345,6 +98320,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) codeInteger(pParse, pExpr, 0, target); return target; } + case TK_TRUEFALSE: { + sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target); + return target; + } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); @@ -95500,6 +98479,18 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeAddOp2(v, op, r1, inReg); break; } + case TK_TRUTH: { + int isTrue; /* IS TRUE or IS NOT TRUE */ + int bNormal; /* IS TRUE or IS FALSE */ + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + bNormal = pExpr->op2==TK_IS; + testcase( isTrue && bNormal); + testcase( !isTrue && bNormal); + sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); + break; + } case TK_ISNULL: case TK_NOTNULL: { int addr; @@ -95671,9 +98662,21 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, - constMask, r1, target, (char*)pDef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nFarg); +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){ + Expr *pArg = pFarg->a[0].pExpr; + if( pArg->op==TK_COLUMN ){ + sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + }else +#endif + { + sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, + constMask, r1, target, (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nFarg); + } if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); } @@ -95738,7 +98741,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { - return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + pExpr = pExpr->pLeft; + goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ } case TK_TRIGGER: { @@ -95776,10 +98780,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); - VdbeComment((v, "%s.%s -> $%d", + VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), - target + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -96111,6 +99114,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( pItem->bSorterRef ){ + i--; + n--; + }else +#endif if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ if( flags & SQLITE_ECEL_OMITREF ){ i--; @@ -96263,6 +99272,23 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_TRUTH: { + int isNot; /* IS NOT TRUE or IS NOT FALSE */ + int isTrue; /* IS TRUE or IS NOT TRUE */ + testcase( jumpIfNull==0 ); + isNot = pExpr->op2==TK_ISNOT; + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + testcase( isTrue && isNot ); + testcase( !isTrue && isNot ); + if( isTrue ^ isNot ){ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + }else{ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + } + break; + } case TK_IS: case TK_ISNOT: testcase( op==TK_IS ); @@ -96417,6 +99443,26 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_TRUTH: { + int isNot; /* IS NOT TRUE or IS NOT FALSE */ + int isTrue; /* IS TRUE or IS NOT TRUE */ + testcase( jumpIfNull==0 ); + isNot = pExpr->op2==TK_ISNOT; + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + testcase( isTrue && isNot ); + testcase( !isTrue && isNot ); + if( isTrue ^ isNot ){ + /* IS TRUE and IS NOT FALSE */ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? 0 : SQLITE_JUMPIFNULL); + + }else{ + /* IS FALSE and IS NOT TRUE */ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? 0 : SQLITE_JUMPIFNULL); + } + break; + } case TK_IS: case TK_ISNOT: testcase( pExpr->op==TK_IS ); @@ -96602,8 +99648,10 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( pA->op==TK_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; + }else if( pA->op==TK_COLLATE ){ + if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ - return pA->op==TK_COLLATE ? 1 : 2; + return 2; } } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; @@ -96612,7 +99660,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; - if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ + assert( (combinedFlags & EP_Reduced)==0 ); + if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; @@ -96704,6 +99753,105 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i return 0; } +/* +** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). +** If the expression node requires that the table at pWalker->iCur +** have a non-NULL column, then set pWalker->eCode to 1 and abort. +*/ +static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + /* This routine is only called for WHERE clause expressions and so it + ** cannot have any TK_AGG_COLUMN entries because those are only found + ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause, + ** but that is an illegal construct and the query will be rejected at + ** a later stage of processing, so the TK_AGG_FUNCTION case does not + ** need to be considered here. */ + assert( pExpr->op!=TK_AGG_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + + if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; + switch( pExpr->op ){ + case TK_ISNOT: + case TK_NOT: + case TK_ISNULL: + case TK_IS: + case TK_OR: + case TK_CASE: + case TK_IN: + case TK_FUNCTION: + testcase( pExpr->op==TK_ISNOT ); + testcase( pExpr->op==TK_NOT ); + testcase( pExpr->op==TK_ISNULL ); + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_OR ); + testcase( pExpr->op==TK_CASE ); + testcase( pExpr->op==TK_IN ); + testcase( pExpr->op==TK_FUNCTION ); + return WRC_Prune; + case TK_COLUMN: + if( pWalker->u.iCur==pExpr->iTable ){ + pWalker->eCode = 1; + return WRC_Abort; + } + return WRC_Prune; + + /* Virtual tables are allowed to use constraints like x=NULL. So + ** a term of the form x=y does not prove that y is not null if x + ** is the column of a virtual table */ + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) + || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + ){ + return WRC_Prune; + } + default: + return WRC_Continue; + } +} + +/* +** Return true (non-zero) if expression p can only be true if at least +** one column of table iTab is non-null. In other words, return true +** if expression p will always be NULL or false if every column of iTab +** is NULL. +** +** False negatives are acceptable. In other words, it is ok to return +** zero even if expression p will never be true of every column of iTab +** is NULL. A false negative is merely a missed optimization opportunity. +** +** False positives are not allowed, however. A false positive may result +** in an incorrect answer. +** +** Terms of p that are marked with EP_FromJoin (and hence that come from +** the ON or USING clauses of LEFT JOINS) are excluded from the analysis. +** +** This routine is used to check if a LEFT JOIN can be converted into +** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE +** clause requires that some column of the right table of the LEFT JOIN +** be non-NULL, then the LEFT JOIN can be safely converted into an +** ordinary join. +*/ +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ + Walker w; + w.xExprCallback = impliesNotNullRow; + w.xSelectCallback = 0; + w.xSelectCallback2 = 0; + w.eCode = 0; + w.u.iCur = iTab; + sqlite3WalkExpr(&w, p); + return w.eCode; +} + /* ** An instance of the following structure is used by the tree walker ** to determine if an expression can be evaluated by reference to the @@ -96859,8 +100007,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ NameContext *pNC = pWalker->u.pNC; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; - AggInfo *pAggInfo = pNC->pAggInfo; + AggInfo *pAggInfo = pNC->uNC.pAggInfo; + assert( pNC->ncFlags & NC_UAggInfo ); switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { @@ -98167,6 +101316,10 @@ static void openStatTable( "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zDbSName, zTab, zWhereType, zWhere ); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + }else if( db->xPreUpdateCallback ){ + sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab); +#endif }else{ /* The sqlite_stat[134] table already exists. Delete all rows. */ sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); @@ -98931,6 +102084,9 @@ static void analyzeOneTable( int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ int regPrev = iMem; /* MUST BE LAST (see below) */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + Table *pStat1 = 0; +#endif pParse->nMem = MAX(pParse->nMem, iMem); v = sqlite3GetVdbe(pParse); @@ -98941,7 +102097,7 @@ static void analyzeOneTable( /* Do not gather statistics on views or virtual tables */ return; } - if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ + if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ /* Do not gather statistics on system tables */ return; } @@ -98956,6 +102112,18 @@ static void analyzeOneTable( } #endif +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + if( db->xPreUpdateCallback ){ + pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13); + if( pStat1==0 ) return; + pStat1->zName = (char*)&pStat1[1]; + memcpy(pStat1->zName, "sqlite_stat1", 13); + pStat1->nCol = 3; + pStat1->iPKey = -1; + sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB); + } +#endif + /* Establish a read-lock on the table at the shared-cache level. ** Open a read-only cursor on the table. Also allocate a cursor number ** to use for scanning indexes (iIdxCur). No index cursor is opened at @@ -99157,6 +102325,9 @@ static void analyzeOneTable( sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); +#endif sqlite3VdbeChangeP5(v, OPFLAG_APPEND); /* Add the entries to the stat3 or stat4 table. */ @@ -99220,6 +102391,9 @@ static void analyzeOneTable( sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); +#endif sqlite3VdbeJumpHere(v, jZeroRows); } } @@ -99902,6 +103076,10 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. +** +** If the db->init.reopenMemdb flags is set, then instead of attaching a +** new database, close the database on db->init.iDb and reopen it as an +** empty MemDB. */ static void attachFunc( sqlite3_context *context, @@ -99922,66 +103100,86 @@ static void attachFunc( sqlite3_vfs *pVfs; UNUSED_PARAMETER(NotUsed); - zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; - /* Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - for(i=0; inDb; i++){ - char *z = db->aDb[i].zDbSName; - assert( z && zName ); - if( sqlite3StrICmp(z, zName)==0 ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); +#ifdef SQLITE_ENABLE_DESERIALIZE +# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) +#else +# define REOPEN_AS_MEMDB(db) (0) +#endif + + if( REOPEN_AS_MEMDB(db) ){ + /* This is not a real ATTACH. Instead, this routine is being called + ** from sqlite3_deserialize() to close database db->init.iDb and + ** reopen it as a MemDB */ + pVfs = sqlite3_vfs_find("memdb"); + if( pVfs==0 ) return; + pNew = &db->aDb[db->init.iDb]; + if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); + pNew->pBt = 0; + pNew->pSchema = 0; + rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + }else{ + /* This is a real ATTACH + ** + ** Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); goto attach_error; } + for(i=0; inDb; i++){ + char *z = db->aDb[i].zDbSName; + assert( z && zName ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialize the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = aNew; + pNew = &db->aDb[db->nDb]; + memset(pNew, 0, sizeof(*pNew)); + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialized. + */ + flags = db->openFlags; + rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + assert( pVfs ); + flags |= SQLITE_OPEN_MAIN_DB; + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + sqlite3_free( zPath ); + db->nDb++; } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = aNew; - pNew = &db->aDb[db->nDb]; - memset(pNew, 0, sizeof(*pNew)); - - /* Open the database file. If the btree is successfully opened, use - ** it to obtain the database schema. At this point the schema may - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); - sqlite3_free( zPath ); - db->nDb++; - db->skipBtreeMutex = 0; + db->noSharedCache = 0; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf(db, "database is already attached"); @@ -100007,7 +103205,7 @@ static void attachFunc( sqlite3BtreeLeave(pNew->pBt); } pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -100047,13 +103245,16 @@ static void attachFunc( /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the way - ** we found it. + ** remove the entry from the db->aDb[] array. i.e. put everything back the + ** way we found it. */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); + db->init.iDb = 0; + db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); + assert( zErrDyn==0 || rc!=SQLITE_OK ); } #ifdef SQLITE_USER_AUTHENTICATION if( rc==SQLITE_OK ){ @@ -100065,21 +103266,23 @@ static void attachFunc( } #endif if( rc ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + if( !REOPEN_AS_MEMDB(db) ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetAllSchemasOfConnection(db); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + } } goto attach_error; } @@ -100321,6 +103524,9 @@ SQLITE_PRIVATE int sqlite3FixSrcList( if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif + if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){ + return 1; + } } return 0; } @@ -100351,8 +103557,13 @@ SQLITE_PRIVATE int sqlite3FixSelect( if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ return 1; } - if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ - return 1; + if( pSelect->pWith ){ + int i; + for(i=0; ipWith->nCte; i++){ + if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){ + return 1; + } + } } pSelect = pSelect->pPrior; } @@ -100415,6 +103626,18 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( if( sqlite3FixExprList(pFix, pStep->pExprList) ){ return 1; } +#ifndef SQLITE_OMIT_UPSERT + if( pStep->pUpsert ){ + Upsert *pUp = pStep->pUpsert; + if( sqlite3FixExprList(pFix, pUp->pUpsertTarget) + || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere) + || sqlite3FixExprList(pFix, pUp->pUpsertSet) + || sqlite3FixExpr(pFix, pUp->pUpsertWhere) + ){ + return 1; + } + } +#endif pStep = pStep->pNext; } return 0; @@ -100575,6 +103798,7 @@ SQLITE_PRIVATE void sqlite3AuthRead( int iDb; /* The index of the database the expression refers to */ int iCol; /* Index of column in table */ + assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema); if( iDb<0 ){ @@ -100583,7 +103807,6 @@ SQLITE_PRIVATE void sqlite3AuthRead( return; } - assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); if( pExpr->op==TK_TRIGGER ){ pTab = pParse->pTriggerTab; }else{ @@ -101042,24 +104265,27 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( const char *zDbase /* Name of the database. Might be NULL */ ){ Table *p; + sqlite3 *db = pParse->db; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 + && SQLITE_OK!=sqlite3ReadSchema(pParse) + ){ return 0; } - p = sqlite3FindTable(pParse->db, zName, zDbase); + p = sqlite3FindTable(db, zName, zDbase); if( p==0 ){ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ + if( sqlite3FindDbName(db, zDbase)<1 ){ /* If zName is the not the name of a table in the schema created using ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ - Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); + Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(pParse->db, zName); + pMod = sqlite3PragmaVtabRegister(db, zName); } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ return pMod->pEpoTab; @@ -101224,6 +104450,7 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); DbSetProperty(db, iDb, DB_ResetWanted); DbSetProperty(db, 1, DB_ResetWanted); + db->mDbFlags &= ~DBFLAG_SchemaKnownOk; } if( db->nSchemaLock==0 ){ @@ -101249,7 +104476,7 @@ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ sqlite3SchemaClear(pDb->pSchema); } } - db->mDbFlags &= ~DBFLAG_SchemaChange; + db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); sqlite3CollapseDatabaseArray(db); @@ -101794,15 +105021,20 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity - ** 'BLOB'. */ + ** 'BLOB' with a default size of 4 bytes. */ pCol->affinity = SQLITE_AFF_BLOB; pCol->szEst = 1; +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( 4>=sqlite3GlobalConfig.szSorterRef ){ + pCol->colFlags |= COLFLAG_SORTERREF; + } +#endif }else{ zType = z + sqlite3Strlen30(z) + 1; memcpy(zType, pType->z, pType->n); zType[pType->n] = 0; sqlite3Dequote(zType); - pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); + pCol->affinity = sqlite3AffinityType(zType, pCol); pCol->colFlags |= COLFLAG_HASTYPE; } p->nCol++; @@ -101817,10 +105049,24 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ */ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ Table *p; + Column *pCol; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; - p->aCol[p->nCol-1].notNull = (u8)onError; + pCol = &p->aCol[p->nCol-1]; + pCol->notNull = (u8)onError; p->tabFlags |= TF_HasNotNull; + + /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created + ** on this column. */ + if( pCol->colFlags & COLFLAG_UNIQUE ){ + Index *pIdx; + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None ); + if( pIdx->aiColumn[0]==p->nCol-1 ){ + pIdx->uniqNotNull = 1; + } + } + } } /* @@ -101848,7 +105094,7 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ +SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const char *zChar = 0; @@ -101885,27 +105131,32 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ } } - /* If pszEst is not NULL, store an estimate of the field size. The + /* If pCol is not NULL, store an estimate of the field size. The ** estimate is scaled so that the size of an integer is 1. */ - if( pszEst ){ - *pszEst = 1; /* default size is approx 4 bytes */ + if( pCol ){ + int v = 0; /* default size is approx 4 bytes */ if( aff r=(k/4+1) */ sqlite3GetInt32(zChar, &v); - v = v/4 + 1; - if( v>255 ) v = 255; - *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ break; } zChar++; } }else{ - *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ + v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ } } +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( v>=sqlite3GlobalConfig.szSorterRef ){ + pCol->colFlags |= COLFLAG_SORTERREF; + } +#endif + v = v/4 + 1; + if( v>255 ) v = 255; + pCol->szEst = v; } return aff; } @@ -101920,34 +105171,37 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ +SQLITE_PRIVATE void sqlite3AddDefaultValue( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The parsed expression of the default value */ + const char *zStart, /* Start of the default value text */ + const char *zEnd /* First character past end of defaut value text */ +){ Table *p; Column *pCol; sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){ + if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. The 'span' of the expression - ** is required by pragma table_info. + ** tokens that point to volatile memory. */ Expr x; sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; - x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); - x.pLeft = pSpan->pExpr; + x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); + x.pLeft = pExpr; x.flags = EP_Skip; pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); sqlite3DbFree(db, x.u.zToken); } } - sqlite3ExprDelete(db, pSpan->pExpr); + sqlite3ExprDelete(db, pExpr); } /* @@ -102178,7 +105432,7 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, - db->aDb[iDb].pSchema->schema_cookie+1); + (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); } /* @@ -102552,8 +105806,6 @@ SQLITE_PRIVATE void sqlite3EndTable( p = pParse->pNewTable; if( p==0 ) return; - assert( !db->init.busy || !pSelect ); - /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -102564,6 +105816,10 @@ SQLITE_PRIVATE void sqlite3EndTable( ** table itself. So mark it read-only. */ if( db->init.busy ){ + if( pSelect ){ + sqlite3ErrorMsg(pParse, ""); + return; + } p->tnum = db->init.newTnum; if( p->tnum==1 ) p->tabFlags |= TF_Readonly; } @@ -102664,10 +105920,6 @@ SQLITE_PRIVATE void sqlite3EndTable( pParse->nTab = 2; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - sqlite3Select(pParse, pSelect, &dest); - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); if( pParse->nErr ) return; pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); if( pSelTab==0 ) return; @@ -102677,6 +105929,11 @@ SQLITE_PRIVATE void sqlite3EndTable( pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(db, pSelTab); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + sqlite3Select(pParse, pSelect, &dest); + if( pParse->nErr ) return; + sqlite3VdbeEndCoroutine(v, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); @@ -102819,7 +106076,7 @@ SQLITE_PRIVATE void sqlite3CreateView( ** the end. */ sEnd = pParse->sLastToken; - assert( sEnd.z[0]!=0 ); + assert( sEnd.z[0]!=0 || sEnd.n==0 ); if( sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } @@ -102853,7 +106110,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ -#ifndef SQLITE_OMIT_VIRTUALTABLE +#ifndef SQLITE_OMIT_VIRTUALTABLE int rc; #endif #ifndef SQLITE_OMIT_AUTHORIZATION @@ -103508,6 +106765,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); + sqlite3MultiWrite(pParse); sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); @@ -103521,12 +106779,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); if( IsUniqueIndex(pIndex) ){ - int j2 = sqlite3VdbeCurrentAddr(v) + 3; - sqlite3VdbeGoto(v, j2); + int j2 = sqlite3VdbeGoto(v, 1); addr2 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeVerifyAbortable(v, OE_Abort); sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); + sqlite3VdbeJumpHere(v, j2); }else{ addr2 = sqlite3VdbeCurrentAddr(v); } @@ -103689,7 +106948,11 @@ SQLITE_PRIVATE void sqlite3CreateIndex( #if SQLITE_USER_AUTHENTICATION && sqlite3UserAuthTable(pTab->zName)==0 #endif - && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ +#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX + && sqlite3StrICmp(&pTab->zName[7],"master")!=0 +#endif + && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 + ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } @@ -103780,7 +107043,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex( */ if( pList==0 ){ Token prevCol; - sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); + Column *pCol = &pTab->aCol[pTab->nCol-1]; + pCol->colFlags |= COLFLAG_UNIQUE; + sqlite3TokenInit(&prevCol, pCol->zName); pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; @@ -104551,9 +107816,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( goto append_from_error; } p = sqlite3SrcListAppend(db, p, pTable, pDatabase); - if( p==0 || NEVER(p->nSrc==0) ){ + if( p==0 ){ goto append_from_error; } + assert( p->nSrc>0 ); pItem = &p->a[p->nSrc-1]; assert( pAlias!=0 ); if( pAlias->n ){ @@ -104865,16 +108131,16 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); if( pIdx->aColExpr ){ - sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); + sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); }else{ for(j=0; jnKeyCol; j++){ char *zCol; assert( pIdx->aiColumn[j]>=0 ); zCol = pTab->aCol[pIdx->aiColumn[j]].zName; - if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3StrAccumAppendAll(&errMsg, pTab->zName); - sqlite3StrAccumAppend(&errMsg, ".", 1); - sqlite3StrAccumAppendAll(&errMsg, zCol); + if( j ) sqlite3_str_append(&errMsg, ", ", 2); + sqlite3_str_appendall(&errMsg, pTab->zName); + sqlite3_str_append(&errMsg, ".", 1); + sqlite3_str_appendall(&errMsg, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); @@ -105062,6 +108328,18 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } if( pParse->nErr ){ + assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); + if( pIdx->bNoQuery==0 ){ + /* Deactivate the index because it contains an unknown collating + ** sequence. The only way to reactive the index is to reload the + ** schema. Adding the missing collating sequence later does not + ** reactive the index. The application had the chance to register + ** the missing index using the collation-needed callback. For + ** simplicity, SQLite will not give the application a second chance. + */ + pIdx->bNoQuery = 1; + pParse->rc = SQLITE_ERROR_RETRY; + } sqlite3KeyInfoUnref(pKey); pKey = 0; } @@ -105247,6 +108525,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( assert( !p || p->xCmp ); if( p==0 ){ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); + pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ; } return p; } @@ -105547,10 +108826,12 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( if( createFlag && bestScorezName = (const char*)&pBest[1]; pBest->nArg = (u16)nArg; pBest->funcFlags = enc; memcpy((char*)&pBest[1], zName, nName+1); + for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z]; pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); if( pOther==pBest ){ sqlite3DbFree(db, pBest); @@ -105720,6 +109001,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ Table *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ + ExprList *pOrderBy, /* Optional ORDER BY clause */ + Expr *pLimit, /* Optional LIMIT clause */ int iCur /* Cursor number for ephemeral table */ ){ SelectDest dest; @@ -105736,8 +109019,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView( assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, - SF_IncludeHidden, 0, 0); + pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, + SF_IncludeHidden, pLimit); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); @@ -105759,29 +109042,29 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( Expr *pWhere, /* The WHERE clause. May be null */ ExprList *pOrderBy, /* The ORDER BY clause. May be null */ Expr *pLimit, /* The LIMIT clause. May be null */ - Expr *pOffset, /* The OFFSET clause. May be null */ char *zStmtType /* Either DELETE or UPDATE. For err msgs. */ ){ - Expr *pWhereRowid = NULL; /* WHERE rowid .. */ + sqlite3 *db = pParse->db; + Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - Expr *pSelectRowid = NULL; /* SELECT rowid ... */ ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ Select *pSelect = NULL; /* Complete SELECT tree */ + Table *pTab; /* Check that there isn't an ORDER BY without a LIMIT clause. */ - if( pOrderBy && (pLimit == 0) ) { + if( pOrderBy && pLimit==0 ) { sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); - goto limit_where_cleanup; + sqlite3ExprDelete(pParse->db, pWhere); + sqlite3ExprListDelete(pParse->db, pOrderBy); + return 0; } /* We only need to generate a select expression if there ** is a limit/offset term to enforce. */ if( pLimit == 0 ) { - /* if pLimit is null, pOffset will always be null as well. */ - assert( pOffset == 0 ); return pWhere; } @@ -105794,36 +109077,47 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( ** ); */ - pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); - if( pSelectRowid == 0 ) goto limit_where_cleanup; - pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); - if( pEList == 0 ) goto limit_where_cleanup; + pTab = pSrc->a[0].pTab; + if( HasRowid(pTab) ){ + pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0); + pEList = sqlite3ExprListAppend( + pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0) + ); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + if( pPk->nKeyCol==1 ){ + const char *zName = pTab->aCol[pPk->aiColumn[0]].zName; + pLhs = sqlite3Expr(db, TK_ID, zName); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName)); + }else{ + int i; + for(i=0; inKeyCol; i++){ + Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName); + pEList = sqlite3ExprListAppend(pParse, pEList, p); + } + pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( pLhs ){ + pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); + } + } + } /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ + pSrc->a[0].pTab = 0; pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); - if( pSelectSrc == 0 ) { - sqlite3ExprListDelete(pParse->db, pEList); - goto limit_where_cleanup; - } + pSrc->a[0].pTab = pTab; + pSrc->a[0].pIBIndex = 0; /* generate the SELECT expression tree. */ - pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, - pOrderBy,0,pLimit,pOffset); - if( pSelect == 0 ) return 0; + pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, + pOrderBy,0,pLimit + ); /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); - pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; + pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; - -limit_where_cleanup: - sqlite3ExprDelete(pParse->db, pWhere); - sqlite3ExprListDelete(pParse->db, pOrderBy); - sqlite3ExprDelete(pParse->db, pLimit); - sqlite3ExprDelete(pParse->db, pOffset); - return 0; } #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ /* && !defined(SQLITE_OMIT_SUBQUERY) */ @@ -105838,7 +109132,9 @@ limit_where_cleanup: SQLITE_PRIVATE void sqlite3DeleteFrom( Parse *pParse, /* The parser context */ SrcList *pTabList, /* The table from which we should delete things */ - Expr *pWhere /* The WHERE clause. May be null */ + Expr *pWhere, /* The WHERE clause. May be null */ + ExprList *pOrderBy, /* ORDER BY clause. May be null */ + Expr *pLimit /* LIMIT clause. May be null */ ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ @@ -105853,7 +109149,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ - int memCnt = -1; /* Memory cell used for change counting */ + int memCnt = 0; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ @@ -105883,6 +109179,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } assert( pTabList->nSrc==1 ); + /* Locate the table which we want to delete. This table has to be ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect @@ -105897,16 +109194,26 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); isView = pTab->pSelect!=0; - bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #else # define pTrigger 0 # define isView 0 #endif + bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT + if( !isView ){ + pWhere = sqlite3LimitWhere( + pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE" + ); + pOrderBy = 0; + pLimit = 0; + } +#endif + /* If pTab is really a view, make sure it has been initialized. */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ @@ -105947,15 +109254,19 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3BeginWriteOperation(pParse, bComplex, iDb); /* If we are trying to delete from a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ - sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur); + sqlite3MaterializeView(pParse, pTab, + pWhere, pOrderBy, pLimit, iTabCur + ); iDataCur = iIdxCur = iTabCur; + pOrderBy = 0; + pLimit = 0; } #endif @@ -105971,7 +109282,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ - if( db->flags & SQLITE_CountRows ){ + if( (db->flags & SQLITE_CountRows)!=0 + && !pParse->nested + && !pParse->pTriggerTab + ){ memCnt = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); } @@ -105999,7 +109313,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, + sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, pTab->zName, P4_STATIC); } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ @@ -106044,9 +109358,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); + if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); /* Keep track of the number of rows to be deleted */ - if( db->flags & SQLITE_CountRows ){ + if( memCnt ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } @@ -106149,13 +109464,16 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, OE_Abort); assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; + if( eOnePass==ONEPASS_SINGLE ){ + sqlite3VdbeAddOp1(v, OP_Close, iTabCur); + if( sqlite3IsToplevel(pParse) ){ + pParse->isMultiWrite = 0; + } } + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); + sqlite3VdbeChangeP5(v, OE_Abort); }else #endif { @@ -106189,7 +109507,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + if( memCnt ){ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); @@ -106199,6 +109517,10 @@ delete_from_cleanup: sqlite3AuthContextPop(&sContext); sqlite3SrcListDelete(db, pTabList); sqlite3ExprDelete(db, pWhere); +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + sqlite3ExprListDelete(db, pOrderBy); + sqlite3ExprDelete(db, pLimit); +#endif sqlite3DbFree(db, aToOpen); return; } @@ -106356,7 +109678,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - if( pParse->nested==0 ){ + if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); } if( eMode!=ONEPASS_OFF ){ @@ -106577,6 +109899,8 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ ** iteration of the aggregate loop. */ static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ + assert( context->isError<=0 ); + context->isError = -1; context->skipFlag = 1; } @@ -106643,8 +109967,6 @@ static void lengthFunc( int argc, sqlite3_value **argv ){ - int len; - assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ @@ -106656,13 +109978,17 @@ static void lengthFunc( } case SQLITE_TEXT: { const unsigned char *z = sqlite3_value_text(argv[0]); + const unsigned char *z0; + unsigned char c; if( z==0 ) return; - len = 0; - while( *z ){ - len++; - SQLITE_SKIP_UTF8(z); + z0 = z; + while( (c = *z)!=0 ){ + z++; + if( c>=0xc0 ){ + while( (*z & 0xc0)==0x80 ){ z++; z0++; } + } } - sqlite3_result_int(context, len); + sqlite3_result_int(context, (int)(z-z0)); break; } default: { @@ -106789,7 +110115,7 @@ static void printfFunc( x.apArg = argv+1; sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); str.printfFlags = SQLITE_PRINTF_SQLFUNC; - sqlite3XPrintf(&str, zFormat, &x); + sqlite3_str_appendf(&str, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, SQLITE_DYNAMIC); @@ -107240,16 +110566,20 @@ static int patternCompare( ** c or cx. */ if( c<=0x80 ){ - u32 cx; + char zStop[3]; int bMatch; if( noCase ){ - cx = sqlite3Toupper(c); - c = sqlite3Tolower(c); + zStop[0] = sqlite3Toupper(c); + zStop[1] = sqlite3Tolower(c); + zStop[2] = 0; }else{ - cx = c; + zStop[0] = c; + zStop[1] = 0; } - while( (c2 = *(zString++))!=0 ){ - if( c2!=c && c2!=cx ) continue; + while(1){ + zString += strcspn((const char*)zString, zStop); + if( zString[0]==0 ) break; + zString++; bMatch = patternCompare(zPattern,zString,pInfo,matchOther); if( bMatch!=SQLITE_NOMATCH ) return bMatch; } @@ -107733,6 +111063,8 @@ static void replaceFunc( i64 nOut; /* Maximum size of zOut */ int loopLimit; /* Last zStr[] that might match zPattern[] */ int i, j; /* Loop counters */ + unsigned cntExpand; /* Number zOut expansions */ + sqlite3 *db = sqlite3_context_db_handle(context); assert( argc==3 ); UNUSED_PARAMETER(argc); @@ -107764,33 +111096,40 @@ static void replaceFunc( return; } loopLimit = nStr - nPattern; + cntExpand = 0; for(i=j=0; i<=loopLimit; i++){ if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ zOut[j++] = zStr[i]; }else{ - u8 *zOld; - sqlite3 *db = sqlite3_context_db_handle(context); - nOut += nRep - nPattern; - testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); - if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - sqlite3_free(zOut); - return; - } - zOld = zOut; - zOut = sqlite3_realloc64(zOut, (int)nOut); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - sqlite3_free(zOld); - return; + if( nRep>nPattern ){ + nOut += nRep - nPattern; + testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); + testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); + if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + sqlite3_free(zOut); + return; + } + cntExpand++; + if( (cntExpand&(cntExpand-1))==0 ){ + /* Grow the size of the output buffer only on substitutions + ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */ + u8 *zOld; + zOld = zOut; + zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1)); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + sqlite3_free(zOld); + return; + } + } } memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; } } - assert( j+nStr-i+1==nOut ); + assert( j+nStr-i+1<=nOut ); memcpy(&zOut[j], &zStr[i], nStr-i); j += nStr - i; assert( j<=nOut ); @@ -108179,20 +111518,20 @@ static void groupConcatStep( zSep = ","; nSep = 1; } - if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); + if( zSep ) sqlite3_str_append(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); - if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); + if( zVal ) sqlite3_str_append(pAccum, zVal, nVal); } } static void groupConcatFinalize(sqlite3_context *context){ StrAccum *pAccum; pAccum = sqlite3_aggregate_context(context, 0); if( pAccum ){ - if( pAccum->accError==STRACCUM_TOOBIG ){ + if( pAccum->accError==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(context); - }else if( pAccum->accError==STRACCUM_NOMEM ){ + }else if( pAccum->accError==SQLITE_NOMEM ){ sqlite3_result_error_nomem(context); }else{ sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, @@ -108336,6 +111675,10 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), #ifdef SQLITE_DEBUG FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), +#endif +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| + SQLITE_FUNC_TYPEOF), #endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), @@ -108765,6 +112108,12 @@ static void fkLookupParent( int iCur = pParse->nTab - 1; /* Cursor number to use */ int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ + sqlite3VdbeVerifyAbortable(v, + (!pFKey->isDeferred + && !(pParse->db->flags & SQLITE_DeferFKs) + && !pParse->pToplevel + && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore); + /* If nIncr is less than zero, then check at runtime if there are any ** outstanding constraints to resolve. If there are not, there is no need ** to check if deleting this row resolves any outstanding violations. @@ -109159,7 +112508,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa } pParse->disableTriggers = 1; - sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); + sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0); pParse->disableTriggers = 0; /* If the DELETE has generated immediate foreign key constraint @@ -109172,6 +112521,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa ** constraints are violated. */ if( (db->flags & SQLITE_DeferFKs)==0 ){ + sqlite3VdbeVerifyAbortable(v, OE_Abort); sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, @@ -109717,7 +113067,7 @@ static Trigger *fkActionTrigger( sqlite3ExprListAppend(pParse, 0, pRaise), sqlite3SrcListAppend(db, 0, &tFrom, 0), pWhere, - 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0 ); pWhere = 0; } @@ -110068,11 +113418,12 @@ static int readsTable(Parse *p, int iDb, Table *pTab){ ** first use of table pTab. On 2nd and subsequent uses, the original ** AutoincInfo structure is used. ** -** Three memory locations are allocated: +** Four consecutive registers are allocated: ** -** (1) Register to hold the name of the pTab table. -** (2) Register to hold the maximum ROWID of pTab. -** (3) Register to hold the rowid in sqlite_sequence of pTab +** (1) The name of the pTab table. +** (2) The maximum ROWID of pTab. +** (3) The rowid in sqlite_sequence of pTab +** (4) The original value of the max ROWID in pTab, or NULL if none ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. @@ -110083,11 +113434,26 @@ static int autoIncBegin( Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ + assert( pParse->db->aDb[iDb].pSchema!=0 ); if( (pTab->tabFlags & TF_Autoincrement)!=0 && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; + Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; + + /* Verify that the sqlite_sequence table exists and is an ordinary + ** rowid table with exactly two columns. + ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ + if( pSeqTab==0 + || !HasRowid(pSeqTab) + || IsVirtual(pSeqTab) + || pSeqTab->nCol!=2 + ){ + pParse->nErr++; + pParse->rc = SQLITE_CORRUPT_SEQUENCE; + return 0; + } pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } @@ -110100,7 +113466,7 @@ static int autoIncBegin( pInfo->iDb = iDb; pToplevel->nMem++; /* Register to hold name of table */ pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ - pToplevel->nMem++; /* Rowid in sqlite_sequence */ + pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ } memId = pInfo->regCtr; } @@ -110128,15 +113494,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList autoInc[] = { /* 0 */ {OP_Null, 0, 0, 0}, - /* 1 */ {OP_Rewind, 0, 9, 0}, + /* 1 */ {OP_Rewind, 0, 10, 0}, /* 2 */ {OP_Column, 0, 0, 0}, - /* 3 */ {OP_Ne, 0, 7, 0}, + /* 3 */ {OP_Ne, 0, 9, 0}, /* 4 */ {OP_Rowid, 0, 0, 0}, /* 5 */ {OP_Column, 0, 1, 0}, - /* 6 */ {OP_Goto, 0, 9, 0}, - /* 7 */ {OP_Next, 0, 2, 0}, - /* 8 */ {OP_Integer, 0, 0, 0}, - /* 9 */ {OP_Close, 0, 0, 0} + /* 6 */ {OP_AddImm, 0, 0, 0}, + /* 7 */ {OP_Copy, 0, 0, 0}, + /* 8 */ {OP_Goto, 0, 11, 0}, + /* 9 */ {OP_Next, 0, 2, 0}, + /* 10 */ {OP_Integer, 0, 0, 0}, + /* 11 */ {OP_Close, 0, 0, 0} }; VdbeOp *aOp; pDb = &db->aDb[p->iDb]; @@ -110147,14 +113515,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); if( aOp==0 ) break; aOp[0].p2 = memId; - aOp[0].p3 = memId+1; + aOp[0].p3 = memId+2; aOp[2].p3 = memId; aOp[3].p1 = memId-1; aOp[3].p3 = memId; aOp[3].p5 = SQLITE_JUMPIFNULL; aOp[4].p2 = memId+1; aOp[5].p3 = memId; - aOp[8].p2 = memId; + aOp[6].p1 = memId; + aOp[7].p2 = memId+2; + aOp[7].p1 = memId; + aOp[10].p2 = memId; } } @@ -110201,6 +113572,8 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); + sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId); + VdbeCoverage(v); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); if( aOp==0 ) break; @@ -110338,7 +113711,8 @@ SQLITE_PRIVATE void sqlite3Insert( SrcList *pTabList, /* Name of table into which we are inserting */ Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ - int onError /* How to handle constraint errors */ + int onError, /* How to handle constraint errors */ + Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ @@ -110633,7 +114007,10 @@ SQLITE_PRIVATE void sqlite3Insert( /* Initialize the count of rows to be inserted */ - if( db->flags & SQLITE_CountRows ){ + if( (db->flags & SQLITE_CountRows)!=0 + && !pParse->nested + && !pParse->pTriggerTab + ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } @@ -110653,6 +114030,19 @@ SQLITE_PRIVATE void sqlite3Insert( pParse->nMem += pIdx->nColumn; } } +#ifndef SQLITE_OMIT_UPSERT + if( pUpsert ){ + pTabList->a[0].iCursor = iDataCur; + pUpsert->pUpsertSrc = pTabList; + pUpsert->regData = regData; + pUpsert->iDataCur = iDataCur; + pUpsert->iIdxCur = iIdxCur; + if( pUpsert->pUpsertTarget ){ + sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert); + } + } +#endif + /* This is the top of the main insertion loop */ if( useTempTable ){ @@ -110767,7 +114157,8 @@ SQLITE_PRIVATE void sqlite3Insert( VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); pOp = sqlite3VdbeGetOp(v, -1); - if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ + assert( pOp!=0 ); + if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){ appendFlag = 1; pOp->opcode = OP_NewRowid; pOp->p1 = iDataCur; @@ -110854,7 +114245,7 @@ SQLITE_PRIVATE void sqlite3Insert( int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 + regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); @@ -110877,7 +114268,7 @@ SQLITE_PRIVATE void sqlite3Insert( /* Update the count of rows that are inserted */ - if( (db->flags & SQLITE_CountRows)!=0 ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } @@ -110914,7 +114305,7 @@ insert_end: ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); @@ -110923,6 +114314,7 @@ insert_end: insert_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pList); + sqlite3UpsertDelete(db, pUpsert); sqlite3SelectDelete(db, pSelect); sqlite3IdListDelete(db, pColumn); sqlite3DbFree(db, aRegIdx); @@ -110994,6 +114386,44 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ return !w.eCode; } +/* +** An instance of the ConstraintAddr object remembers the byte-code addresses +** for sections of the constraint checks that deal with uniqueness constraints +** on the rowid and on the upsert constraint. +** +** This information is passed into checkReorderConstraintChecks() to insert +** some OP_Goto operations so that the rowid and upsert constraints occur +** in the correct order relative to other constraints. +*/ +typedef struct ConstraintAddr ConstraintAddr; +struct ConstraintAddr { + int ipkTop; /* Subroutine for rowid constraint check */ + int upsertTop; /* Label for upsert constraint check subroutine */ + int upsertTop2; /* Copy of upsertTop not cleared by the call */ + int upsertBtm; /* upsert constraint returns to this label */ + int ipkBtm; /* Return opcode rowid constraint check */ +}; + +/* +** Generate any OP_Goto operations needed to cause constraints to be +** run that haven't already been run. +*/ +static void reorderConstraintChecks(Vdbe *v, ConstraintAddr *p){ + if( p->upsertTop ){ + testcase( sqlite3VdbeLabelHasBeenResolved(v, p->upsertTop) ); + sqlite3VdbeGoto(v, p->upsertTop); + VdbeComment((v, "call upsert subroutine")); + sqlite3VdbeResolveLabel(v, p->upsertBtm); + p->upsertTop = 0; + } + if( p->ipkTop ){ + sqlite3VdbeGoto(v, p->ipkTop); + VdbeComment((v, "call rowid unique-check subroutine")); + sqlite3VdbeJumpHere(v, p->ipkBtm); + p->ipkTop = 0; + } +} + /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE ** on table pTab. @@ -111089,7 +114519,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( u8 overrideError, /* Override onError to this if not OE_Default */ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ - int *aiChng /* column i is unchanged if aiChng[i]<0 */ + int *aiChng, /* column i is unchanged if aiChng[i]<0 */ + Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ ){ Vdbe *v; /* VDBE under constrution */ Index *pIdx; /* Pointer to one of the indices */ @@ -111102,10 +114533,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int addr1; /* Address of jump instruction */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ - int ipkTop = 0; /* Top of the rowid change constraint check */ - int ipkBottom = 0; /* Bottom of the rowid change constraint check */ + ConstraintAddr sAddr;/* Address information for constraint reordering */ + Index *pUpIdx = 0; /* Index to which to apply the upsert */ u8 isUpdate; /* True if this is an UPDATE operation */ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ + int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */ isUpdate = regOldData!=0; db = pParse->db; @@ -111113,6 +114545,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; + memset(&sAddr, 0, sizeof(sAddr)); /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for ** normal rowid tables. nPkField is the number of key fields in the @@ -111195,6 +114628,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( Expr *pExpr = pCheck->a[i].pExpr; if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; allOk = sqlite3VdbeMakeLabel(v); + sqlite3VdbeVerifyAbortable(v, onError); sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); @@ -111212,6 +114646,46 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } #endif /* !defined(SQLITE_OMIT_CHECK) */ + /* UNIQUE and PRIMARY KEY constraints should be handled in the following + ** order: + ** + ** (1) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore + ** (2) OE_Update + ** (3) OE_Replace + ** + ** OE_Fail and OE_Ignore must happen before any changes are made. + ** OE_Update guarantees that only a single row will change, so it + ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback + ** could happen in any order, but they are grouped up front for + ** convenience. + ** + ** Constraint checking code is generated in this order: + ** (A) The rowid constraint + ** (B) Unique index constraints that do not have OE_Replace as their + ** default conflict resolution strategy + ** (C) Unique index that do use OE_Replace by default. + ** + ** The ordering of (2) and (3) is accomplished by making sure the linked + ** list of indexes attached to a table puts all OE_Replace indexes last + ** in the list. See sqlite3CreateIndex() for where that happens. + */ + + if( pUpsert ){ + if( pUpsert->pUpsertTarget==0 ){ + /* An ON CONFLICT DO NOTHING clause, without a constraint-target. + ** Make all unique constraint resolution be OE_Ignore */ + assert( pUpsert->pUpsertSet==0 ); + overrideError = OE_Ignore; + pUpsert = 0; + }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){ + /* If the constraint-target is on some column other than + ** then ROWID, then we might need to move the UPSERT around + ** so that it occurs in the correct order. */ + sAddr.upsertTop = sAddr.upsertTop2 = sqlite3VdbeMakeLabel(v); + sAddr.upsertBtm = sqlite3VdbeMakeLabel(v); + } + } + /* If rowid is changing, make sure the new rowid does not previously ** exist in the table. */ @@ -111226,6 +114700,32 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( onError = OE_Abort; } + /* figure out whether or not upsert applies in this case */ + if( pUpsert && pUpsert->pUpsertIdx==0 ){ + if( pUpsert->pUpsertSet==0 ){ + onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ + }else{ + onError = OE_Update; /* DO UPDATE */ + } + } + + /* If the response to a rowid conflict is REPLACE but the response + ** to some other UNIQUE constraint is FAIL or IGNORE, then we need + ** to defer the running of the rowid conflict checking until after + ** the UNIQUE constraints have run. + */ + assert( OE_Update>OE_Replace ); + assert( OE_Ignore=OE_Replace + && (pUpsert || onError!=overrideError) + && pTab->pIndex + ){ + sAddr.ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; + } + if( isUpdate ){ /* pkChng!=0 does not mean that the rowid has changed, only that ** it might have changed. Skip the conflict logic below if the rowid @@ -111235,26 +114735,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( VdbeCoverage(v); } - /* If the response to a rowid conflict is REPLACE but the response - ** to some other UNIQUE constraint is FAIL or IGNORE, then we need - ** to defer the running of the rowid conflict checking until after - ** the UNIQUE constraints have run. - */ - if( onError==OE_Replace && overrideError!=OE_Replace ){ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){ - ipkTop = sqlite3VdbeAddOp0(v, OP_Goto); - break; - } - } - } - /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ + VdbeNoopComment((v, "uniqueness check for ROWID")); + sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); VdbeCoverage(v); - /* Generate code that deals with a rowid collision */ switch( onError ){ default: { onError = OE_Abort; @@ -111263,6 +114750,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( case OE_Rollback: case OE_Abort: case OE_Fail: { + testcase( onError==OE_Rollback ); + testcase( onError==OE_Abort ); + testcase( onError==OE_Fail ); sqlite3RowidConstraint(pParse, onError, pTab); break; } @@ -111299,14 +114789,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( regNewData, 1, 0, OE_Replace, 1, -1); }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( HasRowid(pTab) ){ - /* This OP_Delete opcode fires the pre-update-hook only. It does - ** not modify the b-tree. It is more efficient to let the coming - ** OP_Insert replace the existing entry than it is to delete the - ** existing entry and then insert a new one. */ - sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - } + assert( HasRowid(pTab) ); + /* This OP_Delete opcode fires the pre-update-hook only. It does + ** not modify the b-tree. It is more efficient to let the coming + ** OP_Insert replace the existing entry than it is to delete the + ** existing entry and then insert a new one. */ + sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ sqlite3MultiWrite(pParse); @@ -111316,16 +114805,22 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( seenReplace = 1; break; } +#ifndef SQLITE_OMIT_UPSERT + case OE_Update: { + sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); + /* Fall through */ + } +#endif case OE_Ignore: { - /*assert( seenReplace==0 );*/ + testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } } sqlite3VdbeResolveLabel(v, addrRowidOk); - if( ipkTop ){ - ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, ipkTop); + if( sAddr.ipkTop ){ + sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, sAddr.ipkTop-1); } } @@ -111343,12 +114838,21 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ + if( pUpIdx==pIdx ){ + addrUniqueOk = sAddr.upsertBtm; + upsertBypass = sqlite3VdbeGoto(v, 0); + VdbeComment((v, "Skip upsert subroutine")); + sqlite3VdbeResolveLabel(v, sAddr.upsertTop2); + }else{ + addrUniqueOk = sqlite3VdbeMakeLabel(v); + } + VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName)); if( bAffinityDone==0 ){ sqlite3TableAffinity(v, pTab, regNewData+1); bAffinityDone = 1; } iThisCur = iIdxCur+ix; - addrUniqueOk = sqlite3VdbeMakeLabel(v); + /* Skip partial indices for which the WHERE clause is not true */ if( pIdx->pPartIdxWhere ){ @@ -111408,6 +114912,24 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( onError = OE_Abort; } + /* Figure out if the upsert clause applies to this index */ + if( pUpIdx==pIdx ){ + if( pUpsert->pUpsertSet==0 ){ + onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ + }else{ + onError = OE_Update; /* DO UPDATE */ + } + } + + /* Invoke subroutines to handle IPK replace and upsert prior to running + ** the first REPLACE constraint check. */ + if( onError==OE_Replace ){ + testcase( sAddr.ipkTop ); + testcase( sAddr.upsertTop + && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) ); + reorderConstraintChecks(v, &sAddr); + } + /* Collision detection may be omitted if all of the following are true: ** (1) The conflict resolution algorithm is REPLACE ** (2) The table is a WITHOUT ROWID table @@ -111428,6 +114950,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } /* Check to see if the new index entry will be unique */ + sqlite3ExprCachePush(pParse); + sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); @@ -111489,25 +115013,37 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); + || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); switch( onError ){ case OE_Rollback: case OE_Abort: case OE_Fail: { + testcase( onError==OE_Rollback ); + testcase( onError==OE_Abort ); + testcase( onError==OE_Fail ); sqlite3UniqueConstraint(pParse, onError, pIdx); break; } +#ifndef SQLITE_OMIT_UPSERT + case OE_Update: { + sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix); + /* Fall through */ + } +#endif case OE_Ignore: { + testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } default: { Trigger *pTrigger = 0; assert( onError==OE_Replace ); - sqlite3MultiWrite(pParse); if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } + if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ + sqlite3MultiWrite(pParse); + } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); @@ -111515,13 +115051,19 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( break; } } - sqlite3VdbeResolveLabel(v, addrUniqueOk); + if( pUpIdx==pIdx ){ + sqlite3VdbeJumpHere(v, upsertBypass); + }else{ + sqlite3VdbeResolveLabel(v, addrUniqueOk); + } + sqlite3ExprCachePop(pParse); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); + } - if( ipkTop ){ - sqlite3VdbeGoto(v, ipkTop+1); - sqlite3VdbeJumpHere(v, ipkBottom); - } + testcase( sAddr.ipkTop!=0 ); + testcase( sAddr.upsertTop + && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) ); + reorderConstraintChecks(v, &sAddr); *pbMayReplace = seenReplace; VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); @@ -111864,7 +115406,6 @@ static int xferOptimization( if( pSelect->pLimit ){ return 0; /* SELECT may not have a LIMIT clause */ } - assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ if( pSelect->pPrior ){ return 0; /* SELECT may not be a compound query */ } @@ -112022,6 +115563,7 @@ static int xferOptimization( emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + sqlite3VdbeVerifyAbortable(v, onError); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); VdbeCoverage(v); sqlite3RowidConstraint(pParse, onError, pDest); @@ -112576,6 +116118,24 @@ struct sqlite3_api_routines { int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); void *(*value_pointer)(sqlite3_value*,const char*); + int (*vtab_nochange)(sqlite3_context*); + int (*value_nochange)(sqlite3_value*); + const char *(*vtab_collation)(sqlite3_index_info*,int); + /* Version 3.24.0 and later */ + int (*keyword_count)(void); + int (*keyword_name)(int,const char**,int*); + int (*keyword_check)(const char*,int); + sqlite3_str *(*str_new)(sqlite3*); + char *(*str_finish)(sqlite3_str*); + void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); + void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); + void (*str_append)(sqlite3_str*, const char *zIn, int N); + void (*str_appendall)(sqlite3_str*, const char *zIn); + void (*str_appendchar)(sqlite3_str*, int N, char C); + void (*str_reset)(sqlite3_str*); + int (*str_errcode)(sqlite3_str*); + int (*str_length)(sqlite3_str*); + char *(*str_value)(sqlite3_str*); }; /* @@ -112842,6 +116402,25 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_bind_pointer sqlite3_api->bind_pointer #define sqlite3_result_pointer sqlite3_api->result_pointer #define sqlite3_value_pointer sqlite3_api->value_pointer +/* Version 3.22.0 and later */ +#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange +#define sqlite3_value_nochange sqlite3_api->value_nochange +#define sqlite3_vtab_collation sqlite3_api->vtab_collation +/* Version 3.24.0 and later */ +#define sqlite3_keyword_count sqlite3_api->keyword_count +#define sqlite3_keyword_name sqlite3_api->keyword_name +#define sqlite3_keyword_check sqlite3_api->keyword_check +#define sqlite3_str_new sqlite3_api->str_new +#define sqlite3_str_finish sqlite3_api->str_finish +#define sqlite3_str_appendf sqlite3_api->str_appendf +#define sqlite3_str_vappendf sqlite3_api->str_vappendf +#define sqlite3_str_append sqlite3_api->str_append +#define sqlite3_str_appendall sqlite3_api->str_appendall +#define sqlite3_str_appendchar sqlite3_api->str_appendchar +#define sqlite3_str_reset sqlite3_api->str_reset +#define sqlite3_str_errcode sqlite3_api->str_errcode +#define sqlite3_str_length sqlite3_api->str_length +#define sqlite3_str_value sqlite3_api->str_value #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -113276,7 +116855,26 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_prepare16_v3, sqlite3_bind_pointer, sqlite3_result_pointer, - sqlite3_value_pointer + sqlite3_value_pointer, + /* Version 3.22.0 and later */ + sqlite3_vtab_nochange, + sqlite3_value_nochange, + sqlite3_vtab_collation, + /* Version 3.24.0 and later */ + sqlite3_keyword_count, + sqlite3_keyword_name, + sqlite3_keyword_check, + sqlite3_str_new, + sqlite3_str_finish, + sqlite3_str_appendf, + sqlite3_str_vappendf, + sqlite3_str_append, + sqlite3_str_appendall, + sqlite3_str_appendchar, + sqlite3_str_reset, + sqlite3_str_errcode, + sqlite3_str_length, + sqlite3_str_value }; /* @@ -115379,6 +118977,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** type: Column declaration type. ** notnull: True if 'NOT NULL' is part of column declaration ** dflt_value: The default value for the column, if any. + ** pk: Non-zero for PK fields. */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; @@ -116514,26 +120113,26 @@ static int pragmaVtabConnect( UNUSED_PARAMETER(argc); UNUSED_PARAMETER(argv); sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); + sqlite3_str_appendall(&acc, "CREATE TABLE x"); for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){ - sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); + sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); cSep = ','; } if( i==0 ){ - sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); + sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); cSep = ','; i++; } j = 0; if( pPragma->mPragFlg & PragFlg_Result1 ){ - sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); + sqlite3_str_appendall(&acc, ",arg HIDDEN"); j++; } if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ - sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); + sqlite3_str_appendall(&acc, ",schema HIDDEN"); j++; } - sqlite3StrAccumAppend(&acc, ")", 1); + sqlite3_str_append(&acc, ")", 1); sqlite3StrAccumFinish(&acc); assert( strlen(zBuf) < sizeof(zBuf)-1 ); rc = sqlite3_declare_vtab(db, zBuf); @@ -116685,13 +120284,13 @@ static int pragmaVtabFilter( } } sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); - sqlite3StrAccumAppendAll(&acc, "PRAGMA "); + sqlite3_str_appendall(&acc, "PRAGMA "); if( pCsr->azArg[1] ){ - sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); + sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]); } - sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); + sqlite3_str_appendall(&acc, pTab->pName->zName); if( pCsr->azArg[0] ){ - sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); + sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]); } zSql = sqlite3StrAccumFinish(&acc); if( zSql==0 ) return SQLITE_NOMEM; @@ -116818,7 +120417,7 @@ static void corruptSchema( char *z; if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); - if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); + if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; } @@ -116934,6 +120533,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ const char *zMasterName; int openedTransaction = 0; + assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite3_mutex_held(db->mutex) ); @@ -117004,6 +120604,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ for(i=0; ipBt, i+1, (u32 *)&meta[i]); } + if( (db->flags & SQLITE_ResetDatabase)!=0 ){ + memset(meta, 0, sizeof(meta)); + } pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; /* If opening a non-empty database, check the text encoding. For the @@ -117163,6 +120766,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ } /* All other schemas after the main schema. The "temp" schema must be last */ for(i=db->nDb-1; i>0; i--){ + assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ) return rc; @@ -117184,10 +120788,12 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){ assert( sqlite3_mutex_held(db->mutex) ); if( !db->init.busy ){ rc = sqlite3Init(db, &pParse->zErrMsg); - } - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; + if( rc!=SQLITE_OK ){ + pParse->rc = rc; + pParse->nErr++; + }else if( db->noSharedCache ){ + db->mDbFlags |= DBFLAG_SchemaKnownOk; + } } return rc; } @@ -117262,7 +120868,8 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ */ assert( sqlite3_mutex_held(db->mutex) ); if( pSchema ){ - for(i=0; ALWAYS(inDb); i++){ + for(i=0; 1; i++){ + assert( inDb ); if( db->aDb[i].pSchema==pSchema ){ break; } @@ -117397,7 +121004,7 @@ static int sqlite3Prepare( if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ static const char * const azColName[] = { "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", - "selectid", "order", "from", "detail" + "id", "parent", "notused", "detail" }; int iFirst, mx; if( sParse.explain==2 ){ @@ -117443,8 +121050,6 @@ static int sqlite3Prepare( end_prepare: sqlite3ParserReset(&sParse); - rc = sqlite3ApiExit(db, rc); - assert( (rc&db->errMask)==rc ); return rc; } static int sqlite3LockAndPrepare( @@ -117457,6 +121062,7 @@ static int sqlite3LockAndPrepare( const char **pzTail /* OUT: End of parsed string */ ){ int rc; + int cnt = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; @@ -117467,15 +121073,18 @@ static int sqlite3LockAndPrepare( } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); - rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); - if( rc==SQLITE_SCHEMA ){ - sqlite3ResetOneSchema(db, -1); - sqlite3_finalize(*ppStmt); + do{ + /* Make multiple attempts to compile the SQL, until it either succeeds + ** or encounters a permanent error. A schema problem after one schema + ** reset is considered a permanent error. */ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); - } + assert( rc==SQLITE_OK || *ppStmt==0 ); + }while( rc==SQLITE_ERROR_RETRY + || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) ); sqlite3BtreeLeaveAll(db); + rc = sqlite3ApiExit(db, rc); + assert( (rc&db->errMask)==rc ); sqlite3_mutex_leave(db->mutex); - assert( rc==SQLITE_OK || *ppStmt==0 ); return rc; } @@ -117709,8 +121318,7 @@ SQLITE_API int sqlite3_prepare16_v3( /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ if(sqlite3SelectTrace&(K)) \ - sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ - (S)->zSelName,(S)),\ + sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\ sqlite3DebugPrintf X #else # define SELECTTRACE(K,P,S,X) @@ -117733,6 +121341,20 @@ struct DistinctCtx { /* ** An instance of the following object is used to record information about ** the ORDER BY (or GROUP BY) clause of query is being coded. +** +** The aDefer[] array is used by the sorter-references optimization. For +** example, assuming there is no index that can be used for the ORDER BY, +** for the query: +** +** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10; +** +** it may be more efficient to add just the "a" values to the sorter, and +** retrieve the associated "bigblob" values directly from table t1 as the +** 10 smallest "a" values are extracted from the sorter. +** +** When the sorter-reference optimization is used, there is one entry in the +** aDefer[] array for each database table that may be read as values are +** extracted from the sorter. */ typedef struct SortCtx SortCtx; struct SortCtx { @@ -117745,6 +121367,15 @@ struct SortCtx { int labelDone; /* Jump here when done, ex: LIMIT reached */ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + u8 nDefer; /* Number of valid entries in aDefer[] */ + struct DeferredCsr { + Table *pTab; /* Table definition */ + int iCsr; /* Cursor number for table */ + int nKey; /* Number of PK columns for table pTab (>=1) */ + } aDefer[4]; +#endif + struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ @@ -117762,7 +121393,6 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); - sqlite3ExprDelete(db, p->pOffset); if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; @@ -117795,8 +121425,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ u32 selFlags, /* Flag parameters, such as SF_Distinct */ - Expr *pLimit, /* LIMIT value. NULL means not used */ - Expr *pOffset /* OFFSET value. NULL means no offset */ + Expr *pLimit /* LIMIT value. NULL means not used */ ){ Select *pNew; Select standin; @@ -117829,10 +121458,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->pPrior = 0; pNew->pNext = 0; pNew->pLimit = pLimit; - pNew->pOffset = pOffset; pNew->pWith = 0; - assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 - || pParse->db->mallocFailed!=0 ); if( pParse->db->mallocFailed ) { clearSelect(pParse->db, pNew, pNew!=&standin); pNew = 0; @@ -118076,6 +121702,29 @@ static void setJoinExpr(Expr *p, int iTable){ } } +/* Undo the work of setJoinExpr(). In the expression tree p, convert every +** term that is marked with EP_FromJoin and iRightJoinTable==iTable into +** an ordinary term that omits the EP_FromJoin mark. +** +** This happens when a LEFT JOIN is simplified into an ordinary JOIN. +*/ +static void unsetJoinExpr(Expr *p, int iTable){ + while( p ){ + if( ExprHasProperty(p, EP_FromJoin) + && (iTable<0 || p->iRightJoinTable==iTable) ){ + ExprClearProperty(p, EP_FromJoin); + } + if( p->op==TK_FUNCTION && p->x.pList ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); + } + } + unsetJoinExpr(p->pLeft, iTable); + p = p->pRight; + } +} + /* ** This routine processes the join information for a SELECT statement. ** ON and USING clauses are converted into extra terms of the WHERE clause. @@ -118185,6 +121834,62 @@ static KeyInfo *keyInfoFromExprList( int nExtra /* Add this many extra columns to the end */ ); +/* +** An instance of this object holds information (beyond pParse and pSelect) +** needed to load the next result row that is to be added to the sorter. +*/ +typedef struct RowLoadInfo RowLoadInfo; +struct RowLoadInfo { + int regResult; /* Store results in array of registers here */ + u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + ExprList *pExtra; /* Extra columns needed by sorter refs */ + int regExtraResult; /* Where to load the extra columns */ +#endif +}; + +/* +** This routine does the work of loading query data into an array of +** registers so that it can be added to the sorter. +*/ +static void innerLoopLoadRow( + Parse *pParse, /* Statement under construction */ + Select *pSelect, /* The query being coded */ + RowLoadInfo *pInfo /* Info needed to complete the row load */ +){ + sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, + 0, pInfo->ecelFlags); +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( pInfo->pExtra ){ + sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); + sqlite3ExprListDelete(pParse->db, pInfo->pExtra); + } +#endif +} + +/* +** Code the OP_MakeRecord instruction that generates the entry to be +** added into the sorter. +** +** Return the register in which the result is stored. +*/ +static int makeSorterRecord( + Parse *pParse, + SortCtx *pSort, + Select *pSelect, + int regBase, + int nBase +){ + int nOBSat = pSort->nOBSat; + Vdbe *v = pParse->pVdbe; + int regOut = ++pParse->nMem; + if( pSort->pDeferredRowLoad ){ + innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); + return regOut; +} + /* ** Generate code that will push the record in registers regData ** through regData+nData-1 onto the sorter. @@ -118195,7 +121900,7 @@ static void pushOntoSorter( Select *pSelect, /* The whole SELECT statement */ int regData, /* First register holding data to be sorted */ int regOrigData, /* First register holding data before packing */ - int nData, /* Number of elements in the data array */ + int nData, /* Number of elements in the regData data array */ int nPrefixReg /* No. of reg prior to regData available for use */ ){ Vdbe *v = pParse->pVdbe; /* Stmt under construction */ @@ -118203,16 +121908,32 @@ static void pushOntoSorter( int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ int regBase; /* Regs for sorter record */ - int regRecord = ++pParse->nMem; /* Assembled sorter record */ + int regRecord = 0; /* Assembled sorter record */ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ + int iSkip = 0; /* End of the sorter insert loop */ assert( bSeq==0 || bSeq==1 ); + + /* Three cases: + ** (1) The data to be sorted has already been packed into a Record + ** by a prior OP_MakeRecord. In this case nData==1 and regData + ** will be completely unrelated to regOrigData. + ** (2) All output columns are included in the sort record. In that + ** case regData==regOrigData. + ** (3) Some output columns are omitted from the sort record due to + ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the + ** SQLITE_ECEL_OMITREF optimization, or due to the + ** SortCtx.pDeferredRowLoad optimiation. In any of these cases + ** regOrigData is 0 to prevent this routine from trying to copy + ** values that might not yet exist. + */ assert( nData==1 || regData==regOrigData || regOrigData==0 ); + if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); - regBase = regData - nExpr - bSeq; + regBase = regData - nPrefixReg; }else{ regBase = pParse->nMem + 1; pParse->nMem += nBase; @@ -118228,7 +121949,6 @@ static void pushOntoSorter( if( nPrefixReg==0 && nData>0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ int addrFirst; /* Address of the OP_IfNot opcode */ @@ -118237,6 +121957,7 @@ static void pushOntoSorter( int nKey; /* Number of sorting key columns, including OP_Sequence */ KeyInfo *pKI; /* Original KeyInfo on the sorter table */ + regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); regPrevKey = pParse->nMem+1; pParse->nMem += pSort->nOBSat; nKey = nExpr - pSort->nOBSat + bSeq; @@ -118270,6 +121991,34 @@ static void pushOntoSorter( sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); sqlite3VdbeJumpHere(v, addrJmp); } + if( iLimit ){ + /* At this point the values for the new sorter entry are stored + ** in an array of registers. They need to be composed into a record + ** and inserted into the sorter if either (a) there are currently + ** less than LIMIT+OFFSET items or (b) the new record is smaller than + ** the largest record currently in the sorter. If (b) is true and there + ** are already LIMIT+OFFSET items in the sorter, delete the largest + ** entry before inserting the new one. This way there are never more + ** than LIMIT+OFFSET items in the sorter. + ** + ** If the new record does not need to be inserted into the sorter, + ** jump to the next iteration of the loop. Or, if the + ** pSort->bOrderedInnerLoop flag is set to indicate that the inner + ** loop delivers items in sorted order, jump to the next iteration + ** of the outer loop. + */ + int iCsr = pSort->iECursor; + sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); + iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, + iCsr, 0, regBase+nOBSat, nExpr-nOBSat); + VdbeCoverage(v); + sqlite3VdbeAddOp1(v, OP_Delete, iCsr); + } + if( regRecord==0 ){ + regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); + } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ @@ -118277,33 +122026,10 @@ static void pushOntoSorter( } sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, regBase+nOBSat, nBase-nOBSat); - if( iLimit ){ - int addr; - int r1 = 0; - /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit - ** register is initialized with value of LIMIT+OFFSET.) After the sorter - ** fills up, delete the least entry in the sorter after each insert. - ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ - addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); - if( pSort->bOrderedInnerLoop ){ - r1 = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); - VdbeComment((v, "seq")); - } - sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); - if( pSort->bOrderedInnerLoop ){ - /* If the inner loop is driven by an index such that values from - ** the same iteration of the inner loop are in sorted order, then - ** immediately jump to the next iteration of an inner loop if the - ** entry from the current iteration does not fit into the top - ** LIMIT+OFFSET entries of the sorter. */ - int iBrk = sqlite3VdbeCurrentAddr(v) + 2; - sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - VdbeCoverage(v); - } - sqlite3VdbeJumpHere(v, addr); + if( iSkip ){ + assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 ); + sqlite3VdbeChangeP2(v, iSkip, + sqlite3VdbeCurrentAddr(v) + pSort->bOrderedInnerLoop); } } @@ -118349,6 +122075,87 @@ static void codeDistinct( sqlite3ReleaseTempReg(pParse, r1); } +#ifdef SQLITE_ENABLE_SORTER_REFERENCES +/* +** This function is called as part of inner-loop generation for a SELECT +** statement with an ORDER BY that is not optimized by an index. It +** determines the expressions, if any, that the sorter-reference +** optimization should be used for. The sorter-reference optimization +** is used for SELECT queries like: +** +** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10 +** +** If the optimization is used for expression "bigblob", then instead of +** storing values read from that column in the sorter records, the PK of +** the row from table t1 is stored instead. Then, as records are extracted from +** the sorter to return to the user, the required value of bigblob is +** retrieved directly from table t1. If the values are very large, this +** can be more efficient than storing them directly in the sorter records. +** +** The ExprList_item.bSorterRef flag is set for each expression in pEList +** for which the sorter-reference optimization should be enabled. +** Additionally, the pSort->aDefer[] array is populated with entries +** for all cursors required to evaluate all selected expressions. Finally. +** output variable (*ppExtra) is set to an expression list containing +** expressions for all extra PK values that should be stored in the +** sorter records. +*/ +static void selectExprDefer( + Parse *pParse, /* Leave any error here */ + SortCtx *pSort, /* Sorter context */ + ExprList *pEList, /* Expressions destined for sorter */ + ExprList **ppExtra /* Expressions to append to sorter record */ +){ + int i; + int nDefer = 0; + ExprList *pExtra = 0; + for(i=0; inExpr; i++){ + struct ExprList_item *pItem = &pEList->a[i]; + if( pItem->u.x.iOrderByCol==0 ){ + Expr *pExpr = pItem->pExpr; + Table *pTab = pExpr->pTab; + if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) + && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) + ){ + int j; + for(j=0; jaDefer[j].iCsr==pExpr->iTable ) break; + } + if( j==nDefer ){ + if( nDefer==ArraySize(pSort->aDefer) ){ + continue; + }else{ + int nKey = 1; + int k; + Index *pPk = 0; + if( !HasRowid(pTab) ){ + pPk = sqlite3PrimaryKeyIndex(pTab); + nKey = pPk->nKeyCol; + } + for(k=0; kiTable = pExpr->iTable; + pNew->pTab = pExpr->pTab; + pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; + pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); + } + } + pSort->aDefer[nDefer].pTab = pExpr->pTab; + pSort->aDefer[nDefer].iCsr = pExpr->iTable; + pSort->aDefer[nDefer].nKey = nKey; + nDefer++; + } + } + pItem->bSorterRef = 1; + } + } + } + pSort->nDefer = (u8)nDefer; + *ppExtra = pExtra; +} +#endif + /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. @@ -118375,6 +122182,7 @@ static void selectInnerLoop( int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nPrefixReg = 0; /* Number of extra registers before regResult */ + RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ /* Usually, regResult is the first cell in an array of memory cells ** containing the current result row. In this case regOrig is set to the @@ -118421,10 +122229,14 @@ static void selectInnerLoop( VdbeComment((v, "%s", p->pEList->a[i].zName)); } }else if( eDest!=SRT_Exists ){ +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + ExprList *pExtra = 0; +#endif /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - u8 ecelFlags; + u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ + ExprList *pEList; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ @@ -118438,18 +122250,68 @@ static void selectInnerLoop( ** This allows the p->pEList field to be omitted from the sorted record, ** saving space and CPU cycles. */ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); + for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){ int j; if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; } } - regOrig = 0; +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + selectExprDefer(pParse, pSort, p->pEList, &pExtra); + if( pExtra && pParse->db->mallocFailed==0 ){ + /* If there are any extra PK columns to add to the sorter records, + ** allocate extra memory cells and adjust the OpenEphemeral + ** instruction to account for the larger records. This is only + ** required if there are one or more WITHOUT ROWID tables with + ** composite primary keys in the SortCtx.aDefer[] array. */ + VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); + pOp->p2 += (pExtra->nExpr - pSort->nDefer); + pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer); + pParse->nMem += pExtra->nExpr; + } +#endif + + /* Adjust nResultCol to account for columns that are omitted + ** from the sorter by the optimizations in this branch */ + pEList = p->pEList; + for(i=0; inExpr; i++){ + if( pEList->a[i].u.x.iOrderByCol>0 +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + || pEList->a[i].bSorterRef +#endif + ){ + nResultCol--; + regOrig = 0; + } + } + + testcase( regOrig ); + testcase( eDest==SRT_Set ); + testcase( eDest==SRT_Mem ); + testcase( eDest==SRT_Coroutine ); + testcase( eDest==SRT_Output ); assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } - nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, - 0,ecelFlags); + sRowLoadInfo.regResult = regResult; + sRowLoadInfo.ecelFlags = ecelFlags; +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + sRowLoadInfo.pExtra = pExtra; + sRowLoadInfo.regExtraResult = regResult + nResultCol; + if( pExtra ) nResultCol += pExtra->nExpr; +#endif + if( p->iLimit + && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 + && nPrefixReg>0 + ){ + assert( pSort!=0 ); + assert( hasDistinct==0 ); + pSort->pDeferredRowLoad = &sRowLoadInfo; + regOrig = 0; + }else{ + innerLoopLoadRow(pParse, p, &sRowLoadInfo); + } } /* If the DISTINCT keyword was present on the SELECT statement @@ -118565,7 +122427,8 @@ static void selectInnerLoop( } #endif if( pSort ){ - pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); + assert( regResult==regOrig ); + pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); }else{ int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); @@ -118832,11 +122695,7 @@ static const char *selectOpName(int id){ ** is determined by the zUsage argument. */ static void explainTempTable(Parse *pParse, const char *zUsage){ - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } + ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); } /* @@ -118854,42 +122713,6 @@ static void explainTempTable(Parse *pParse, const char *zUsage){ # define explainSetInteger(y,z) #endif -#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) -/* -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function -** is a no-op. Otherwise, it adds a single row of output to the EQP result, -** where the caption is of one of the two forms: -** -** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" -** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" -** -** where iSub1 and iSub2 are the integers passed as the corresponding -** function parameters, and op is the text representation of the parameter -** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, -** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is -** false, or the second form if it is true. -*/ -static void explainComposite( - Parse *pParse, /* Parse context */ - int op, /* One of TK_UNION, TK_EXCEPT etc. */ - int iSub1, /* Subquery id 1 */ - int iSub2, /* Subquery id 2 */ - int bUseTmp /* True if a temp table was used */ -){ - assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf( - pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, - bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } -} -#else -/* No-op versions of the explainXXX() functions and macros. */ -# define explainComposite(v,w,x,y,z) -#endif /* ** If the inner loop was generated using a non-null pOrderBy argument, @@ -118907,7 +122730,7 @@ static void generateSortTail( Vdbe *v = pParse->pVdbe; /* The prepared statement */ int addrBreak = pSort->labelDone; /* Jump here to exit loop */ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ - int addr; + int addr; /* Top of output loop. Jump for Next. */ int addrOnce = 0; int iTab; ExprList *pOrderBy = pSort->pOrderBy; @@ -118916,11 +122739,11 @@ static void generateSortTail( int regRow; int regRowid; int iCol; - int nKey; + int nKey; /* Number of key columns in sorter record */ int iSortTab; /* Sorter cursor to read from */ - int nSortData; /* Trailing values to read from sorter */ int i; int bSeq; /* True if sorter record includes seq. no. */ + int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; assert( addrBreak<0 ); @@ -118929,15 +122752,24 @@ static void generateSortTail( sqlite3VdbeGoto(v, addrBreak); sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } + +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + /* Open any cursors needed for sorter-reference expressions */ + for(i=0; inDefer; i++){ + Table *pTab = pSort->aDefer[i].pTab; + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); + nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); + } +#endif + iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ regRowid = 0; regRow = pDest->iSdst; - nSortData = nColumn; }else{ regRowid = sqlite3GetTempReg(pParse); regRow = sqlite3GetTempRange(pParse, nColumn); - nSortData = nColumn; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ @@ -118946,7 +122778,8 @@ static void generateSortTail( if( pSort->labelBkOut ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } - sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); + sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, + nKey+1+nColumn+nRefKey); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); @@ -118959,15 +122792,59 @@ static void generateSortTail( iSortTab = iTab; bSeq = 1; } - for(i=0, iCol=nKey+bSeq; inDefer ){ + int iKey = iCol+1; + int regKey = sqlite3GetTempRange(pParse, nRefKey); + + for(i=0; inDefer; i++){ + int iCsr = pSort->aDefer[i].iCsr; + Table *pTab = pSort->aDefer[i].pTab; + int nKey = pSort->aDefer[i].nKey; + + sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey); + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr, + sqlite3VdbeCurrentAddr(v)+1, regKey); + }else{ + int k; + int iJmp; + assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey ); + for(k=0; k=0; i--){ +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( aOutEx[i].bSorterRef ){ + sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); + }else +#endif + { + int iRead; + if( aOutEx[i].u.x.iOrderByCol ){ + iRead = aOutEx[i].u.x.iOrderByCol-1; + }else{ + iRead = iCol--; + } + sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); + VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan)); } - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); - VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } switch( eDest ){ case SRT_Table: @@ -119074,8 +122951,9 @@ static const char *columnTypeImpl( assert( pExpr!=0 ); assert( pNC->pSrcList!=0 ); + assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates + ** are processed */ switch( pExpr->op ){ - case TK_AGG_COLUMN: case TK_COLUMN: { /* The expression is a column. Locate the table the column is being ** extracted from in NameContext.pSrcList. This table may be real @@ -119084,8 +122962,6 @@ static const char *columnTypeImpl( Table *pTab = 0; /* Table structure column is extracted from */ Select *pS = 0; /* Select the column is extracted from */ int iCol = pExpr->iColumn; /* Index of column in pTab */ - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_COLUMN ); while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); @@ -119286,9 +123162,10 @@ static void generateColumnNames( } #endif - if( pParse->colNamesSet || db->mallocFailed ) return; + if( pParse->colNamesSet ) return; /* Column names are determined by the left-most term of a compound select */ while( pSelect->pPrior ) pSelect = pSelect->pPrior; + SELECTTRACE(1,pParse,pSelect,("generating column names\n")); pTabList = pSelect->pSrc; pEList = pSelect->pEList; assert( v!=0 ); @@ -119397,12 +123274,12 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } - if( (pColExpr->op==TK_COLUMN || pColExpr->op==TK_AGG_COLUMN) - && pColExpr->pTab!=0 - ){ + assert( pColExpr->op!=TK_AGG_COLUMN ); + if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; Table *pTab = pColExpr->pTab; + assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; }else if( pColExpr->op==TK_ID ){ @@ -119562,7 +123439,7 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ /* ** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit and pOffset expressions. pLimit and pOffset hold the expressions +** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset ** are the integer memory register numbers for counters used to compute @@ -119570,15 +123447,15 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ ** iLimit and iOffset are negative. ** ** This routine changes the values of iLimit and iOffset only if -** a limit or offset is defined by pLimit and pOffset. iLimit and -** iOffset should have been preset to appropriate default values (zero) +** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit +** and iOffset should have been preset to appropriate default values (zero) ** prior to calling this routine. ** ** The iOffset register (if it exists) is initialized to the value ** of the OFFSET. The iLimit register is initialized to LIMIT. Register ** iOffset+1 is initialized to LIMIT+OFFSET. ** -** Only if pLimit!=0 or pOffset!=0 do the limit registers get +** Only if pLimit->pLeft!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. @@ -119588,6 +123465,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ int iLimit = 0; int iOffset; int n; + Expr *pLimit = p->pLimit; + if( p->iLimit ) return; /* @@ -119597,12 +123476,13 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ ** no rows. */ sqlite3ExprCacheClear(pParse); - assert( p->pOffset==0 || p->pLimit!=0 ); - if( p->pLimit ){ + if( pLimit ){ + assert( pLimit->op==TK_LIMIT ); + assert( pLimit->pLeft!=0 ); p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); assert( v!=0 ); - if( sqlite3ExprIsInteger(p->pLimit, &n) ){ + if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); if( n==0 ){ @@ -119612,15 +123492,15 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ p->selFlags |= SF_FixedLimit; } }else{ - sqlite3ExprCode(pParse, p->pLimit, iLimit); + sqlite3ExprCode(pParse, pLimit->pLeft, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); } - if( p->pOffset ){ + if( pLimit->pRight ){ p->iOffset = iOffset = ++pParse->nMem; pParse->nMem++; /* Allocate an extra register for limit+offset */ - sqlite3ExprCode(pParse, p->pOffset, iOffset); + sqlite3ExprCode(pParse, pLimit->pRight, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); @@ -119750,7 +123630,7 @@ static void generateWithRecursiveQuery( int i; /* Loop counter */ int rc; /* Result code */ ExprList *pOrderBy; /* The ORDER BY clause */ - Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ + Expr *pLimit; /* Saved LIMIT and OFFSET */ int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ /* Obtain authorization to do a recursive query */ @@ -119761,10 +123641,9 @@ static void generateWithRecursiveQuery( p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, addrBreak); pLimit = p->pLimit; - pOffset = p->pOffset; regLimit = p->iLimit; regOffset = p->iOffset; - p->pLimit = p->pOffset = 0; + p->pLimit = 0; p->iLimit = p->iOffset = 0; pOrderBy = p->pOrderBy; @@ -119810,6 +123689,7 @@ static void generateWithRecursiveQuery( /* Store the results of the setup-query in Queue. */ pSetup->pNext = 0; + ExplainQueryPlan((pParse, 1, "SETUP")); rc = sqlite3Select(pParse, pSetup, &destQueue); pSetup->pNext = p; if( rc ) goto end_of_recursive_query; @@ -119844,6 +123724,7 @@ static void generateWithRecursiveQuery( sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); }else{ p->pPrior = 0; + ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); sqlite3Select(pParse, p, &destQueue); assert( p->pPrior==0 ); p->pPrior = pSetup; @@ -119857,7 +123738,6 @@ end_of_recursive_query: sqlite3ExprListDelete(pParse->db, p->pOrderBy); p->pOrderBy = pOrderBy; p->pLimit = pLimit; - p->pOffset = pOffset; return; } #endif /* SQLITE_OMIT_CTE */ @@ -119876,36 +123756,38 @@ static int multiSelectOrderBy( ** on a VALUES clause. ** ** Because the Select object originates from a VALUES clause: -** (1) It has no LIMIT or OFFSET +** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1 ** (2) All terms are UNION ALL ** (3) There is no ORDER BY clause +** +** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES +** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))"). +** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case. +** Since the limit is exactly 1, we only need to evalutes the left-most VALUES. */ static int multiSelectValues( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ){ - Select *pPrior; int nRow = 1; int rc = 0; + int bShowAll = p->pLimit==0; assert( p->selFlags & SF_MultiValue ); do{ assert( p->selFlags & SF_Values ); assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); - assert( p->pLimit==0 ); - assert( p->pOffset==0 ); assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); if( p->pPrior==0 ) break; assert( p->pPrior->pNext==p ); p = p->pPrior; - nRow++; + nRow += bShowAll; }while(1); + ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, + nRow==1 ? "" : "S")); while( p ){ - pPrior = p->pPrior; - p->pPrior = 0; - rc = sqlite3Select(pParse, p, pDest); - p->pPrior = pPrior; - if( rc ) break; + selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); + if( !bShowAll ) break; p->nSelectRow = nRow; p = p->pNext; } @@ -119954,10 +123836,6 @@ static int multiSelect( SelectDest dest; /* Alternative data destination */ Select *pDelete = 0; /* Chain of simple selects to delete */ sqlite3 *db; /* Database connection */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1 = 0; /* EQP id of left-hand query */ - int iSub2 = 0; /* EQP id of right-hand query */ -#endif /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. @@ -120008,226 +123886,231 @@ static int multiSelect( */ if( p->pOrderBy ){ return multiSelectOrderBy(pParse, p, pDest); - }else + }else{ - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - int addr = 0; - int nLimit; - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = p->pLimit; - pPrior->pOffset = p->pOffset; - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &dest); - p->pLimit = 0; - p->pOffset = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); - } - } - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( pPrior->pLimit - && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - } - break; +#ifndef SQLITE_OMIT_EXPLAIN + if( pPrior->pPrior==0 ){ + ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); + ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temporary table holding result */ - u8 op = 0; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ - int addr; - SelectDest uniondest; +#endif - testcase( p->op==TK_EXCEPT ); - testcase( p->op==TK_UNION ); - priorOp = SRT_Union; - if( dest.eDest==priorOp ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + int nLimit; + assert( !pPrior->pLimit ); + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; + rc = sqlite3Select(pParse, pPrior, &dest); + p->pLimit = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); + } + } + ExplainQueryPlan((pParse, 1, "UNION ALL")); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + if( pPrior->pLimit + && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) + ){ + p->nSelectRow = sqlite3LogEst((u64)nLimit); + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temp table holding result */ + u8 op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit; /* Saved values of p->nLimit */ + int addr; + SelectDest uniondest; + + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); + priorOp = SRT_Union; + if( dest.eDest==priorOp ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + assert( p->pLimit==0 ); /* Not allowed on leftward elements */ + unionTab = dest.iSDParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + } + + /* Code the SELECT statements to our left */ - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ - assert( p->pOffset==0 ); /* Not allowed on leftward elements */ - unionTab = dest.iSDParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement */ - unionTab = pParse->nTab++; + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(db, p->pOrderBy); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->iLimit = 0; + p->iOffset = 0; + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); + if( dest.eDest!=priorOp ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, unionTab, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + default: assert( p->op==TK_INTERSECT ); { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit; + int addr; + SelectDest intersectdest; + int r1; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; assert( p->pOrderBy==0 ); - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; findRightmost(p)->selFlags |= SF_UsesEphemeral; assert( p->pEList ); - } - - /* Code the SELECT statements to our left - */ - assert( !pPrior->pOrderBy ); - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &uniondest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT statement - */ - if( p->op==TK_EXCEPT ){ - op = SRT_Except; - }else{ - assert( p->op==TK_UNION ); - op = SRT_Union; - } - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - pOffset = p->pOffset; - p->pOffset = 0; - uniondest.eDest = op; - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &uniondest); - testcase( rc!=SQLITE_OK ); - /* Query flattening in sqlite3Select() might refill p->pOrderBy. - ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ - sqlite3ExprListDelete(db, p->pOrderBy); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->pOrderBy = 0; - if( p->op==TK_UNION ){ - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->pOffset = pOffset; - p->iLimit = 0; - p->iOffset = 0; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); - if( dest.eDest!=priorOp ){ - int iCont, iBreak, iStart; + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( p->nSelectRow>pPrior->nSelectRow ){ + p->nSelectRow = pPrior->nSelectRow; + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + + /* Generate code to take the intersection of the two temporary + ** tables. + */ assert( p->pEList ); iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); - iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, unionTab, + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; } - break; } - default: assert( p->op==TK_INTERSECT ); { - int tab1, tab2; - int iCont, iBreak, iStart; - Expr *pLimit, *pOffset; - int addr; - SelectDest intersectdest; - int r1; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - assert( p->pOrderBy==0 ); - - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &intersectdest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT into temporary table "tab2" - */ - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); - assert( p->addrOpenEphm[1] == -1 ); - p->addrOpenEphm[1] = addr; - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - pOffset = p->pOffset; - p->pOffset = 0; - intersectdest.iSDParm = tab2; - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &intersectdest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->pOffset = pOffset; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - assert( p->pEList ); - iBreak = sqlite3VdbeMakeLabel(v); - iCont = sqlite3VdbeMakeLabel(v); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); - r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, tab1, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); - break; + + #ifndef SQLITE_OMIT_EXPLAIN + if( p->pNext==0 ){ + ExplainQueryPlanPop(pParse); } + #endif } - - explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); - + /* Compute collating sequences used by ** temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. @@ -120565,10 +124448,6 @@ static int multiSelectOrderBy( ExprList *pOrderBy; /* The ORDER BY clause */ int nOrderBy; /* Number of terms in the ORDER BY clause */ int *aPermute; /* Mapping from ORDER BY terms to result set columns */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1; /* EQP id of left-hand query */ - int iSub2; /* EQP id of right-hand query */ -#endif assert( p->pOrderBy!=0 ); assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ @@ -120680,8 +124559,6 @@ static int multiSelectOrderBy( } sqlite3ExprDelete(db, p->pLimit); p->pLimit = 0; - sqlite3ExprDelete(db, p->pOffset); - p->pOffset = 0; regAddrA = ++pParse->nMem; regAddrB = ++pParse->nMem; @@ -120690,6 +124567,8 @@ static int multiSelectOrderBy( sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); + ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op))); + /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. */ @@ -120697,7 +124576,7 @@ static int multiSelectOrderBy( addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; - explainSetInteger(iSub1, pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "LEFT")); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); @@ -120712,7 +124591,7 @@ static int multiSelectOrderBy( savedOffset = p->iOffset; p->iLimit = regLimitB; p->iOffset = 0; - explainSetInteger(iSub2, pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "RIGHT")); sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; @@ -120824,7 +124703,7 @@ static int multiSelectOrderBy( /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ - explainComposite(pParse, p->op, iSub1, iSub2, 0); + ExplainQueryPlanPop(pParse); return pParse->nErr!=0; } #endif @@ -121071,12 +124950,11 @@ static void substSelect( ** (19) If the subquery uses LIMIT then the outer query may not ** have a WHERE clause. ** -** (**) Subsumed into (17d3). Was: If the sub-query is a compound select, -** then it must not use an ORDER BY clause - Ticket #3773. Because -** of (17d3), then only way to have a compound subquery is if it is -** the only term in the FROM clause of the outer query. But if the -** only term in the FROM clause has an ORDER BY, then it will be -** implemented as a co-routine and the flattener will never be called. +** (20) If the sub-query is a compound select, then it must not use +** an ORDER BY clause. Ticket #3773. We could relax this constraint +** somewhat by saying that the terms of the ORDER BY clause must +** appear as unmodified result columns in the outer query. But we +** have other optimizations in mind to deal with that case. ** ** (21) If the subquery uses LIMIT then the outer query may not be ** DISTINCT. (See ticket [752e1646fc]). @@ -121146,7 +125024,7 @@ static int flattenSubquery( ** became arbitrary expressions, we were forced to add restrictions (13) ** and (14). */ if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ - if( pSub->pOffset ) return 0; /* Restriction (14) */ + if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */ if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ return 0; /* Restriction (15) */ } @@ -121210,6 +125088,9 @@ static int flattenSubquery( ** queries. */ if( pSub->pPrior ){ + if( pSub->pOrderBy ){ + return 0; /* Restriction (20) */ + } if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ return 0; /* (17d1), (17d2), or (17d3) */ } @@ -121244,15 +125125,6 @@ static int flattenSubquery( */ assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 ); - /* Ex-restriction (20): - ** A compound subquery must be the only term in the FROM clause of the - ** outer query by restriction (17d3). But if that term also has an - ** ORDER BY clause, then the subquery will be implemented by co-routine - ** and so the flattener will never be invoked. Hence, it is not possible - ** for the subquery to be a compound and have an ORDER BY clause. - */ - assert( pSub->pPrior==0 || pSub->pOrderBy==0 ); - /***** If we reach this point, flattening is permitted. *****/ SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", pSub->zSelName, pSub, iFrom)); @@ -121300,16 +125172,13 @@ static int flattenSubquery( Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; - Expr *pOffset = p->pOffset; Select *pPrior = p->pPrior; p->pOrderBy = 0; p->pSrc = 0; p->pPrior = 0; p->pLimit = 0; - p->pOffset = 0; pNew = sqlite3SelectDup(db, p, 0); sqlite3SelectSetName(pNew, pSub->zSelName); - p->pOffset = pOffset; p->pLimit = pLimit; p->pOrderBy = pOrderBy; p->pSrc = pSrc; @@ -121321,9 +125190,8 @@ static int flattenSubquery( if( pPrior ) pPrior->pNext = pNew; pNew->pNext = p; p->pPrior = pNew; - SELECTTRACE(2,pParse,p, - ("compound-subquery flattener creates %s.%p as peer\n", - pNew->zSelName, pNew)); + SELECTTRACE(2,pParse,p,("compound-subquery flattener" + " creates %s.%p as peer\n",pNew->zSelName, pNew)); } if( db->mallocFailed ) return 1; } @@ -121457,7 +125325,6 @@ static int flattenSubquery( pOrderBy->a[i].u.x.iOrderByCol = 0; } assert( pParent->pOrderBy==0 ); - assert( pSub->pPrior==0 ); pParent->pOrderBy = pOrderBy; pSub->pOrderBy = 0; } @@ -121541,12 +125408,22 @@ static int flattenSubquery( ** (3) The inner query has a LIMIT clause (since the changes to the WHERE ** close would change the meaning of the LIMIT). ** -** (4) The inner query is the right operand of a LEFT JOIN. (The caller -** enforces this restriction since this routine does not have enough -** information to know.) +** (4) The inner query is the right operand of a LEFT JOIN and the +** expression to be pushed down does not come from the ON clause +** on that LEFT JOIN. ** ** (5) The WHERE clause expression originates in the ON or USING clause -** of a LEFT JOIN. +** of a LEFT JOIN where iCursor is not the right-hand table of that +** left join. An example: +** +** SELECT * +** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa +** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) +** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); +** +** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). +** But if the (b2=2) term were to be pushed down into the bb subquery, +** then the (1,1,NULL) row would be suppressed. ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. @@ -121555,7 +125432,8 @@ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ - int iCursor /* Cursor number of the subquery */ + int iCursor, /* Cursor number of the subquery */ + int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ ){ Expr *pNew; int nChng = 0; @@ -121579,15 +125457,25 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, + iCursor, isLeftJoin); pWhere = pWhere->pLeft; } - if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */ + if( isLeftJoin + && (ExprHasProperty(pWhere,EP_FromJoin)==0 + || pWhere->iRightJoinTable!=iCursor) + ){ + return 0; /* restriction (4) */ + } + if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ + return 0; /* restriction (5) */ + } if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); + unsetJoinExpr(pNew, -1); x.pParse = pParse; x.iTable = iCursor; x.iNewTable = iCursor; @@ -121607,42 +125495,44 @@ static int pushDownWhereTerms( #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* -** Based on the contents of the AggInfo structure indicated by the first -** argument, this function checks if the following are true: +** The pFunc is the only aggregate function in the query. Check to see +** if the query is a candidate for the min/max optimization. ** -** * the query contains just a single aggregate function, -** * the aggregate function is either min() or max(), and -** * the argument to the aggregate function is a column value. +** If the query is a candidate for the min/max optimization, then set +** *ppMinMax to be an ORDER BY clause to be used for the optimization +** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on +** whether pFunc is a min() or max() function. ** -** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX -** is returned as appropriate. Also, *ppMinMax is set to point to the -** list of arguments passed to the aggregate before returning. +** If the query is not a candidate for the min/max optimization, return +** WHERE_ORDERBY_NORMAL (which must be zero). ** -** Or, if the conditions above are not met, *ppMinMax is set to 0 and -** WHERE_ORDERBY_NORMAL is returned. +** This routine must be called after aggregate functions have been +** located but before their arguments have been subjected to aggregate +** analysis. */ -static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ - int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ +static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ + int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ + ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */ + const char *zFunc; /* Name of aggregate function pFunc */ + ExprList *pOrderBy; + u8 sortOrder; - *ppMinMax = 0; - if( pAggInfo->nFunc==1 ){ - Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ - ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ - - assert( pExpr->op==TK_AGG_FUNCTION ); - if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ - const char *zFunc = pExpr->u.zToken; - if( sqlite3StrICmp(zFunc, "min")==0 ){ - eRet = WHERE_ORDERBY_MIN; - *ppMinMax = pEList; - }else if( sqlite3StrICmp(zFunc, "max")==0 ){ - eRet = WHERE_ORDERBY_MAX; - *ppMinMax = pEList; - } - } + assert( *ppMinMax==0 ); + assert( pFunc->op==TK_AGG_FUNCTION ); + if( pEList==0 || pEList->nExpr!=1 ) return eRet; + zFunc = pFunc->u.zToken; + if( sqlite3StrICmp(zFunc, "min")==0 ){ + eRet = WHERE_ORDERBY_MIN; + sortOrder = SQLITE_SO_ASC; + }else if( sqlite3StrICmp(zFunc, "max")==0 ){ + eRet = WHERE_ORDERBY_MAX; + sortOrder = SQLITE_SO_DESC; + }else{ + return eRet; } - - assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); + *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); + assert( pOrderBy!=0 || db->mallocFailed ); + if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder; return eRet; } @@ -121773,7 +125663,6 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ assert( pNew->pPrior!=0 ); pNew->pPrior->pNext = pNew; pNew->pLimit = 0; - pNew->pOffset = 0; return WRC_Continue; } @@ -122029,19 +125918,19 @@ static int selectExpander(Walker *pWalker, Select *p){ sqlite3 *db = pParse->db; Expr *pE, *pRight, *pExpr; u16 selFlags = p->selFlags; + u32 elistFlags = 0; p->selFlags |= SF_Expanded; if( db->mallocFailed ){ return WRC_Abort; } - if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ + assert( p->pSrc!=0 ); + if( (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } pTabList = p->pSrc; pEList = p->pEList; - if( OK_IF_ALWAYS_TRUE(p->pWith) ){ - sqlite3WithPush(pParse, p->pWith, 0); - } + sqlite3WithPush(pParse, p->pWith, 0); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. @@ -122141,6 +126030,7 @@ static int selectExpander(Walker *pWalker, Select *p){ assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; + elistFlags |= pE->flags; } if( knExpr ){ /* @@ -122156,6 +126046,7 @@ static int selectExpander(Walker *pWalker, Select *p){ for(k=0; knExpr; k++){ pE = a[k].pExpr; + elistFlags |= pE->flags; pRight = pE->pRight; assert( pE->op!=TK_DOT || pRight!=0 ); if( pE->op!=TK_ASTERISK @@ -122285,9 +126176,14 @@ static int selectExpander(Walker *pWalker, Select *p){ sqlite3ExprListDelete(db, pEList); p->pEList = pNew; } - if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns in result set"); - return WRC_Abort; + if( p->pEList ){ + if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns in result set"); + return WRC_Abort; + } + if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){ + p->selFlags |= SF_ComplexResult; + } } return WRC_Continue; } @@ -122595,28 +126491,17 @@ static void explainSimpleCount( ){ if( pParse->explain==2 ){ int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); - char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", + sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s", pTab->zName, bCover ? " USING COVERING INDEX " : "", bCover ? pIdx->zName : "" ); - sqlite3VdbeAddOp4( - pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC - ); } } #else # define explainSimpleCount(a,b,c) #endif -/* -** Context object for havingToWhereExprCb(). -*/ -struct HavingToWhereCtx { - Expr **ppWhere; - ExprList *pGroupBy; -}; - /* ** sqlite3WalkExpr() callback used by havingToWhere(). ** @@ -122630,15 +126515,16 @@ struct HavingToWhereCtx { */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ - struct HavingToWhereCtx *p = pWalker->u.pHavingCtx; - if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){ + Select *pS = pWalker->u.pSelect; + if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){ sqlite3 *db = pWalker->pParse->db; Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0); if( pNew ){ - Expr *pWhere = *(p->ppWhere); + Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); pNew = sqlite3ExprAnd(db, pWhere, pNew); - *(p->ppWhere) = pNew; + pS->pWhere = pNew; + pWalker->eCode = 1; } } return WRC_Prune; @@ -122661,23 +126547,19 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ ** entirely of constants and expressions that are also GROUP BY terms that ** use the "BINARY" collation sequence. */ -static void havingToWhere( - Parse *pParse, - ExprList *pGroupBy, - Expr *pHaving, - Expr **ppWhere -){ - struct HavingToWhereCtx sCtx; +static void havingToWhere(Parse *pParse, Select *p){ Walker sWalker; - - sCtx.ppWhere = ppWhere; - sCtx.pGroupBy = pGroupBy; - memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.xExprCallback = havingToWhereExprCb; - sWalker.u.pHavingCtx = &sCtx; - sqlite3WalkExpr(&sWalker, pHaving); + sWalker.u.pSelect = p; + sqlite3WalkExpr(&sWalker, p->pHaving); +#if SELECTTRACE_ENABLED + if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){ + SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif } /* @@ -122823,21 +126705,18 @@ SQLITE_PRIVATE int sqlite3Select( AggInfo sAggInfo; /* Information used by aggregate queries */ int iEnd; /* Address of the end of the query */ sqlite3 *db; /* The database connection */ - -#ifndef SQLITE_OMIT_EXPLAIN - int iRestoreSelectId = pParse->iSelectId; - pParse->iSelectId = pParse->iNextSelectId++; -#endif + ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ + u8 minMaxFlag; /* Flag for min/max queries */ db = pParse->db; + v = sqlite3GetVdbe(pParse); if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); #if SELECTTRACE_ENABLED - pParse->nSelectIndent++; - SELECTTRACE(1,pParse,p, ("begin processing:\n")); + SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); if( sqlite3SelectTrace & 0x100 ){ sqlite3TreeViewSelect(0, p, 0); } @@ -122868,27 +126747,39 @@ SQLITE_PRIVATE int sqlite3Select( assert( p->pEList!=0 ); isAgg = (p->selFlags & SF_Aggregate)!=0; #if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ - SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); + if( sqlite3SelectTrace & 0x104 ){ + SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif - /* Get a pointer the VDBE under construction, allocating a new VDBE if one - ** does not already exist */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto select_end; if( pDest->eDest==SRT_Output ){ generateColumnNames(pParse, p); } - /* Try to flatten subqueries in the FROM clause up into the main query + /* Try to various optimizations (flattening subqueries, and strength + ** reduction of join operators) in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && inSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; Select *pSub = pItem->pSelect; Table *pTab = pItem->pTab; + + /* Convert LEFT JOIN into JOIN if there are terms of the right table + ** of the LEFT JOIN used in the WHERE clause. + */ + if( (pItem->fg.jointype & JT_LEFT)!=0 + && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) + && OptimizationEnabled(db, SQLITE_SimplifyJoin) + ){ + SELECTTRACE(0x100,pParse,p, + ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); + pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + unsetJoinExpr(p->pWhere, pItem->iCursor); + } + + /* No futher action if this term of the FROM clause is no a subquery */ if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of @@ -122909,7 +126800,9 @@ SQLITE_PRIVATE int sqlite3Select( if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; assert( pSub->pGroupBy==0 ); - /* If the subquery contains an ORDER BY clause and if + /* If the outer query contains a "complex" result set (that is, + ** if the result set of the outer query uses functions or subqueries) + ** and if the subquery contains an ORDER BY clause and if ** it will be implemented as a co-routine, then do not flatten. This ** restriction allows SQL constructs like this: ** @@ -122918,9 +126811,16 @@ SQLITE_PRIVATE int sqlite3Select( ** ** The expensive_function() is only computed on the 10 rows that ** are output, rather than every row of the table. + ** + ** The requirement that the outer query have a complex result set + ** means that flattening does occur on simpler SQL constraints without + ** the expensive_function() like: + ** + ** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10); */ if( pSub->pOrderBy!=0 && i==0 + && (p->selFlags & SF_ComplexResult)!=0 && (pTabList->nSrc==1 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) ){ @@ -122945,11 +126845,13 @@ SQLITE_PRIVATE int sqlite3Select( */ if( p->pPrior ){ rc = multiSelect(pParse, p, pDest); - explainSetInteger(pParse->iSelectId, iRestoreSelectId); #if SELECTTRACE_ENABLED - SELECTTRACE(1,pParse,p,("end compound-select processing\n")); - pParse->nSelectIndent--; + SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); + if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ + sqlite3TreeViewSelect(0, p, 0); + } #endif + if( p->pNext==0 ) ExplainQueryPlanPop(pParse); return rc; } #endif @@ -123021,8 +126923,9 @@ SQLITE_PRIVATE int sqlite3Select( /* Make copies of constant WHERE-clause terms in the outer query down ** inside the subquery. This can help the subquery to run more efficiently. */ - if( (pItem->fg.jointype & JT_OUTER)==0 - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) + if( OptimizationEnabled(db, SQLITE_PushDown) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, + (pItem->fg.jointype & JT_OUTER)!=0) ){ #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ @@ -123030,6 +126933,8 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3TreeViewSelect(0, p, 0); } #endif + }else{ + SELECTTRACE(0x100,pParse,p,("Push-down not possible\n")); } zSavedAuthContext = pParse->zAuthContext; @@ -123058,7 +126963,7 @@ SQLITE_PRIVATE int sqlite3Select( VdbeComment((v, "%s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub)); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; @@ -123093,12 +126998,11 @@ SQLITE_PRIVATE int sqlite3Select( pPrior = isSelfJoinView(pTabList, pItem); if( pPrior ){ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); - explainSetInteger(pItem->iSelectId, pPrior->iSelectId); assert( pPrior->pSelect!=0 ); pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub)); sqlite3Select(pParse, pSub, &dest); } pItem->pTab->nRowLogEst = pSub->nSelectRow; @@ -123232,6 +127136,7 @@ SQLITE_PRIVATE int sqlite3Select( wctrlFlags |= p->selFlags & SF_FixedLimit; /* Begin the database scan. */ + SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; @@ -123324,7 +127229,8 @@ SQLITE_PRIVATE int sqlite3Select( memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; - sNC.pAggInfo = &sAggInfo; + sNC.uNC.pAggInfo = &sAggInfo; + VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) sAggInfo.mnReg = pParse->nMem+1; sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; sAggInfo.pGroupBy = pGroupBy; @@ -123333,12 +127239,19 @@ SQLITE_PRIVATE int sqlite3Select( if( pHaving ){ if( pGroupBy ){ assert( pWhere==p->pWhere ); - havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere); + assert( pHaving==p->pHaving ); + assert( pGroupBy==p->pGroupBy ); + havingToWhere(pParse, p); pWhere = p->pWhere; } sqlite3ExprAnalyzeAggregates(&sNC, pHaving); } sAggInfo.nAccumulator = sAggInfo.nColumn; + if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){ + minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy); + }else{ + minMaxFlag = WHERE_ORDERBY_NORMAL; + } for(i=0; inMem; if( db->mallocFailed ) goto select_end; +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + int ii; + SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n")); + sqlite3TreeViewSelect(0, p, 0); + for(ii=0; iipGroupBy==0 ); - assert( flag==0 ); - if( p->pHaving==0 ){ - flag = minMaxQuery(&sAggInfo, &pMinMax); - } - assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); - - if( flag ){ - pMinMax = sqlite3ExprListDup(db, pMinMax, 0); - pDel = pMinMax; - assert( db->mallocFailed || pMinMax!=0 ); - if( !db->mallocFailed ){ - pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; - pMinMax->a[0].pExpr->op = TK_COLUMN; - } - } - /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ + assert( p->pGroupBy==0 ); resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); + + /* If this query is a candidate for the min/max optimization, then + ** minMaxFlag will have been previously set to either + ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will + ** be an appropriate ORDER BY expression for the optimization. + */ + assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); + assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); + + SELECTTRACE(1,pParse,p,("WhereBegin\n")); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, + 0, minMaxFlag, 0); if( pWInfo==0 ){ - sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); - assert( pMinMax==0 || pMinMax->nExpr==1 ); if( sqlite3WhereIsOrdered(pWInfo)>0 ){ sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); VdbeComment((v, "%s() by index", - (flag==WHERE_ORDERBY_MIN?"min":"max"))); + (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); @@ -123708,7 +127604,6 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, -1, 0, 0, pDest, addrEnd, addrEnd); - sqlite3ExprListDelete(db, pDel); } sqlite3VdbeResolveLabel(v, addrEnd); @@ -123724,6 +127619,7 @@ SQLITE_PRIVATE int sqlite3Select( if( sSort.pOrderBy ){ explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); + assert( p->pEList==pEList ); generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); } @@ -123739,14 +127635,16 @@ SQLITE_PRIVATE int sqlite3Select( ** successful coding of the SELECT. */ select_end: - explainSetInteger(pParse->iSelectId, iRestoreSelectId); - + sqlite3ExprListDelete(db, pMinMaxOrderBy); sqlite3DbFree(db, sAggInfo.aCol); sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED - SELECTTRACE(1,pParse,p,("end processing\n")); - pParse->nSelectIndent--; + SELECTTRACE(0x1,pParse,p,("end processing\n")); + if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ + sqlite3TreeViewSelect(0, p, 0); + } #endif + ExplainQueryPlanPop(pParse); return rc; } @@ -123980,6 +127878,8 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); + sqlite3UpsertDelete(db, pTmp->pUpsert); + sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); } @@ -124294,6 +128194,17 @@ triggerfinish_cleanup: sqlite3DeleteTriggerStep(db, pStepList); } +/* +** Duplicate a range of text from an SQL statement, then convert all +** whitespace characters into ordinary space characters. +*/ +static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ + char *z = sqlite3DbSpanDup(db, zStart, zEnd); + int i; + if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' '; + return z; +} + /* ** Turn a SELECT statement (that the pSelect parameter points to) into ** a trigger step. Return a pointer to a TriggerStep structure. @@ -124301,7 +128212,12 @@ triggerfinish_cleanup: ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ +SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( + sqlite3 *db, /* Database connection */ + Select *pSelect, /* The SELECT statement */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ +){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ) { sqlite3SelectDelete(db, pSelect); @@ -124310,6 +128226,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelec pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); return pTriggerStep; } @@ -124322,7 +128239,9 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelec static TriggerStep *triggerStepAllocate( sqlite3 *db, /* Database connection */ u8 op, /* Trigger opcode */ - Token *pName /* The target name */ + Token *pName, /* The target name */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; @@ -124333,6 +128252,7 @@ static TriggerStep *triggerStepAllocate( sqlite3Dequote(z); pTriggerStep->zTarget = z; pTriggerStep->op = op; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); } return pTriggerStep; } @@ -124349,19 +128269,26 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ Select *pSelect, /* A SELECT statement that supplies values */ - u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ + u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ + Upsert *pUpsert, /* ON CONFLICT clauses for upsert */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; assert(pSelect != 0 || db->mallocFailed); - pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; + pTriggerStep->pUpsert = pUpsert; pTriggerStep->orconf = orconf; }else{ + testcase( pColumn ); sqlite3IdListDelete(db, pColumn); + testcase( pUpsert ); + sqlite3UpsertDelete(db, pUpsert); } sqlite3SelectDelete(db, pSelect); @@ -124378,11 +128305,13 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( Token *pTableName, /* Name of the table to be updated */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ - u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ + u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); @@ -124401,11 +128330,13 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( sqlite3 *db, /* Database connection */ Token *pTableName, /* The table from which rows are deleted */ - Expr *pWhere /* The WHERE clause */ + Expr *pWhere, /* The WHERE clause */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pTriggerStep->orconf = OE_Default; @@ -124660,13 +128591,21 @@ static int codeTriggerProgram( pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; assert( pParse->okConstFactor==0 ); +#ifndef SQLITE_OMIT_TRACE + if( pStep->zSpan ){ + sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, + sqlite3MPrintf(db, "-- %s", pStep->zSpan), + P4_DYNAMIC); + } +#endif + switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), - pParse->eOrconf + pParse->eOrconf, 0, 0, 0 ); break; } @@ -124675,14 +128614,15 @@ static int codeTriggerProgram( targetSrcList(pParse, pStep), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), - pParse->eOrconf + pParse->eOrconf, + sqlite3UpsertDup(db, pStep->pUpsert) ); break; } case TK_DELETE: { sqlite3DeleteFrom(pParse, targetSrcList(pParse, pStep), - sqlite3ExprDup(db, pStep->pWhere, 0) + sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 ); break; } @@ -124800,9 +128740,11 @@ static TriggerPrg *codeRowTrigger( pTab->zName )); #ifndef SQLITE_OMIT_TRACE - sqlite3VdbeChangeP4(v, -1, - sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC - ); + if( pTrigger->zName ){ + sqlite3VdbeChangeP4(v, -1, + sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC + ); + } #endif /* If one was specified, code the WHEN clause. If it evaluates to false @@ -124830,7 +128772,7 @@ static TriggerPrg *codeRowTrigger( VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); transferParseError(pParse, pSubParse); - if( db->mallocFailed==0 ){ + if( db->mallocFailed==0 && pParse->nErr==0 ){ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } pProgram->nMem = pSubParse->nMem; @@ -125149,7 +129091,10 @@ SQLITE_PRIVATE void sqlite3Update( SrcList *pTabList, /* The table in which we should change things */ ExprList *pChanges, /* Things to be changed */ Expr *pWhere, /* The WHERE clause. May be null */ - int onError /* How to handle constraint errors */ + int onError, /* How to handle constraint errors */ + ExprList *pOrderBy, /* ORDER BY clause. May be null */ + Expr *pLimit, /* LIMIT clause. May be null */ + Upsert *pUpsert /* ON CONFLICT clause, or null */ ){ int i, j; /* Loop counters */ Table *pTab; /* The table to be updated */ @@ -125234,6 +129179,16 @@ SQLITE_PRIVATE void sqlite3Update( # define isView 0 #endif +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT + if( !isView ){ + pWhere = sqlite3LimitWhere( + pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" + ); + pOrderBy = 0; + pLimit = 0; + } +#endif + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } @@ -125246,16 +129201,23 @@ SQLITE_PRIVATE void sqlite3Update( ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ - pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; + iBaseCur = iDataCur = pParse->nTab++; iIdxCur = iDataCur+1; pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); + testcase( pPk!=0 && pPk!=pTab->pIndex ); for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ - if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ + if( pPk==pIdx ){ iDataCur = pParse->nTab; - pTabList->a[0].iCursor = iDataCur; } pParse->nTab++; } + if( pUpsert ){ + /* On an UPSERT, reuse the same cursors already opened by INSERT */ + iDataCur = pUpsert->iDataCur; + iIdxCur = pUpsert->iIdxCur; + pParse->nTab = iBaseCur; + } + pTabList->a[0].iCursor = iDataCur; /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. ** Initialize aXRef[] and aToOpen[] to their default values. @@ -125272,6 +129234,8 @@ SQLITE_PRIVATE void sqlite3Update( memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; + sNC.uNC.pUpsert = pUpsert; + sNC.ncFlags = NC_UUpsert; /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index @@ -125375,7 +129339,7 @@ SQLITE_PRIVATE void sqlite3Update( v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); /* Allocate required registers. */ if( !IsVirtual(pTab) ){ @@ -125402,7 +129366,11 @@ SQLITE_PRIVATE void sqlite3Update( */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ - sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur); + sqlite3MaterializeView(pParse, pTab, + pWhere, pOrderBy, pLimit, iDataCur + ); + pOrderBy = 0; + pLimit = 0; } #endif @@ -125422,8 +129390,16 @@ SQLITE_PRIVATE void sqlite3Update( } #endif - /* Initialize the count of updated rows */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ + /* Jump to labelBreak to abandon further processing of this UPDATE */ + labelContinue = labelBreak = sqlite3VdbeMakeLabel(v); + + /* Not an UPSERT. Normal processing. Begin by + ** initialize the count of updated rows */ + if( (db->flags&SQLITE_CountRows)!=0 + && !pParse->pTriggerTab + && !pParse->nested + && pUpsert==0 + ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } @@ -125436,46 +129412,61 @@ SQLITE_PRIVATE void sqlite3Update( iPk = pParse->nMem+1; pParse->nMem += nPk; regKey = ++pParse->nMem; - iEph = pParse->nTab++; - - sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); - addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); - sqlite3VdbeSetP4KeyInfo(pParse, pPk); - } - - /* Begin the database scan. - ** - ** Do not consider a single-pass strategy for a multi-row update if - ** there are any triggers or foreign keys to process, or rows may - ** be deleted as a result of REPLACE conflict handling. Any of these - ** things might disturb a cursor being used to scan through the table - ** or index, causing a single-pass approach to malfunction. */ - flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; - if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ - flags |= WHERE_ONEPASS_MULTIROW; - } - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); - if( pWInfo==0 ) goto update_cleanup; - - /* A one-pass strategy that might update more than one row may not - ** be used if any column of the index used for the scan is being - ** updated. Otherwise, if there is an index on "b", statements like - ** the following could create an infinite loop: - ** - ** UPDATE t1 SET b=b+1 WHERE b>? - ** - ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI - ** strategy that uses an index for which one or more columns are being - ** updated. */ - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - if( eOnePass==ONEPASS_MULTI ){ - int iCur = aiCurOnePass[1]; - if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ - eOnePass = ONEPASS_OFF; + if( pUpsert==0 ){ + iEph = pParse->nTab++; + sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); + addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); + sqlite3VdbeSetP4KeyInfo(pParse, pPk); } - assert( iCur!=iDataCur || !HasRowid(pTab) ); } + if( pUpsert ){ + /* If this is an UPSERT, then all cursors have already been opened by + ** the outer INSERT and the data cursor should be pointing at the row + ** that is to be updated. So bypass the code that searches for the + ** row(s) to be updated. + */ + pWInfo = 0; + eOnePass = ONEPASS_SINGLE; + sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); + }else{ + /* Begin the database scan. + ** + ** Do not consider a single-pass strategy for a multi-row update if + ** there are any triggers or foreign keys to process, or rows may + ** be deleted as a result of REPLACE conflict handling. Any of these + ** things might disturb a cursor being used to scan through the table + ** or index, causing a single-pass approach to malfunction. */ + flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; + if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ + flags |= WHERE_ONEPASS_MULTIROW; + } + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); + if( pWInfo==0 ) goto update_cleanup; + + /* A one-pass strategy that might update more than one row may not + ** be used if any column of the index used for the scan is being + ** updated. Otherwise, if there is an index on "b", statements like + ** the following could create an infinite loop: + ** + ** UPDATE t1 SET b=b+1 WHERE b>? + ** + ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI + ** strategy that uses an index for which one or more columns are being + ** updated. */ + eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); + if( eOnePass!=ONEPASS_SINGLE ){ + sqlite3MultiWrite(pParse); + if( eOnePass==ONEPASS_MULTI ){ + int iCur = aiCurOnePass[1]; + if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ + eOnePass = ONEPASS_OFF; + } + assert( iCur!=iDataCur || !HasRowid(pTab) ); + } + } + } + if( HasRowid(pTab) ){ /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF ** mode, write the rowid into the FIFO. In either of the one-pass modes, @@ -125495,7 +129486,7 @@ SQLITE_PRIVATE void sqlite3Update( sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); } if( eOnePass ){ - sqlite3VdbeChangeToNoop(v, addrOpen); + if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); nKey = nPk; regKey = iPk; }else{ @@ -125505,59 +129496,58 @@ SQLITE_PRIVATE void sqlite3Update( } } - if( eOnePass!=ONEPASS_MULTI ){ - sqlite3WhereEnd(pWInfo); - } - - labelBreak = sqlite3VdbeMakeLabel(v); - if( !isView ){ - int addrOnce = 0; - - /* Open every index that needs updating. */ + if( pUpsert==0 ){ + if( eOnePass!=ONEPASS_MULTI ){ + sqlite3WhereEnd(pWInfo); + } + + if( !isView ){ + int addrOnce = 0; + + /* Open every index that needs updating. */ + if( eOnePass!=ONEPASS_OFF ){ + if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; + if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; + } + + if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, + aToOpen, 0, 0); + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + } + + /* Top of the update loop */ if( eOnePass!=ONEPASS_OFF ){ - if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; - if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; - } - - if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, - 0, 0); - if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); - } - - /* Top of the update loop */ - if( eOnePass!=ONEPASS_OFF ){ - if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ - assert( pPk ); - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); - VdbeCoverageNeverTaken(v); - } - if( eOnePass==ONEPASS_SINGLE ){ - labelContinue = labelBreak; - }else{ + if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ + assert( pPk ); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); + VdbeCoverageNeverTaken(v); + } + if( eOnePass!=ONEPASS_SINGLE ){ + labelContinue = sqlite3VdbeMakeLabel(v); + } + sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); + VdbeCoverageIf(v, pPk==0); + VdbeCoverageIf(v, pPk!=0); + }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); + addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); + VdbeCoverage(v); + }else{ + labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak, + regOldRowid); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); } - sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); - VdbeCoverageIf(v, pPk==0); - VdbeCoverageIf(v, pPk!=0); - }else if( pPk ){ - labelContinue = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); - addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); - VdbeCoverage(v); - }else{ - labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, - regOldRowid); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); - VdbeCoverage(v); } - /* If the record number will change, set register regNewRowid to - ** contain the new value. If the record number is not being modified, + /* If the rowid value will change, set register regNewRowid to + ** contain the new value. If the rowid is not being modified, ** then regNewRowid is the same register as regOldRowid, which is ** already populated. */ assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); @@ -125621,6 +129611,12 @@ SQLITE_PRIVATE void sqlite3Update( testcase( i==31 ); testcase( i==32 ); sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); + if( tmask & TRIGGER_BEFORE ){ + /* This value will be recomputed in After-BEFORE-trigger-reload-loop + ** below, so make sure that it is not cached and reused. + ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */ + sqlite3ExprCacheRemove(pParse, regNew+i, 1); + } }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } @@ -125649,10 +129645,14 @@ SQLITE_PRIVATE void sqlite3Update( VdbeCoverage(v); } - /* If it did not delete it, the row-trigger may still have modified + /* After-BEFORE-trigger-reload-loop: + ** If it did not delete it, the BEFORE trigger may still have modified ** some of the columns of the row being updated. Load the values for - ** all columns not modified by the update statement into their - ** registers in case this has happened. + ** all columns not modified by the update statement into their registers + ** in case this has happened. Only unmodified columns are reloaded. + ** The values computed for modified columns use the values before the + ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) + ** for an example. */ for(i=0; inCol; i++){ if( aXRef[i]<0 && i!=pTab->iPKey ){ @@ -125668,7 +129668,7 @@ SQLITE_PRIVATE void sqlite3Update( assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, - aXRef); + aXRef, 0); /* Do FK constraint checks. */ if( hasFK ){ @@ -125738,7 +129738,7 @@ SQLITE_PRIVATE void sqlite3Update( /* Increment the row counter */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } @@ -125765,16 +129765,15 @@ SQLITE_PRIVATE void sqlite3Update( ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ + if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ sqlite3AutoincrementEnd(pParse); } /* - ** Return the number of rows that were changed. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. + ** Return the number of rows that were changed, if we are tracking + ** that information. */ - if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); @@ -125786,6 +129785,10 @@ update_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pChanges); sqlite3ExprDelete(db, pWhere); +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + sqlite3ExprListDelete(db, pOrderBy); + sqlite3ExprDelete(db, pLimit); +#endif return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise @@ -125842,10 +129845,10 @@ static void updateVirtualTable( int regRowid; /* Register for ephem table rowid */ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ - int bOnePass; /* True to use onepass strategy */ + int eOnePass; /* True to use onepass strategy */ int addr; /* Address of OP_OpenEphemeral */ - /* Allocate nArg registers to martial the arguments to VUpdate. Then + /* Allocate nArg registers in which to gather the arguments for VUpdate. Then ** create and open the ephemeral table in which the records created from ** these arguments will be temporarily stored. */ assert( v ); @@ -125866,6 +129869,7 @@ static void updateVirtualTable( sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); }else{ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); + sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */ } } if( HasRowid(pTab) ){ @@ -125886,26 +129890,32 @@ static void updateVirtualTable( sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); } - bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); - if( bOnePass ){ + /* There is no ONEPASS_MULTI on virtual tables */ + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); + + if( eOnePass ){ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded - ** above. Also, if this is a top-level parse (not a trigger), clear the - ** multi-write flag so that the VM does not open a statement journal */ + ** above. */ sqlite3VdbeChangeToNoop(v, addr); - if( sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; - } + sqlite3VdbeAddOp1(v, OP_Close, iCsr); }else{ /* Create a record from the argument register contents and insert it into ** the ephemeral table. */ + sqlite3MultiWrite(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); +#ifdef SQLITE_DEBUG + /* Signal an assert() within OP_MakeRecord that it is allowed to + ** accept no-change records with serial_type 10 */ + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); +#endif sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); } - if( bOnePass==0 ){ + if( eOnePass==ONEPASS_OFF ){ /* End the virtual table scan */ sqlite3WhereEnd(pWInfo); @@ -125925,7 +129935,7 @@ static void updateVirtualTable( /* End of the ephemeral table scan. Or, if using the onepass strategy, ** jump to here if the scan visited zero rows. */ - if( bOnePass==0 ){ + if( eOnePass==ONEPASS_OFF ){ sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); @@ -125936,6 +129946,259 @@ static void updateVirtualTable( #endif /* SQLITE_OMIT_VIRTUALTABLE */ /************** End of update.c **********************************************/ +/************** Begin file upsert.c ******************************************/ +/* +** 2018-04-12 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement various aspects of UPSERT +** processing and handling of the Upsert object. +*/ +/* #include "sqliteInt.h" */ + +#ifndef SQLITE_OMIT_UPSERT +/* +** Free a list of Upsert objects +*/ +SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){ + if( p ){ + sqlite3ExprListDelete(db, p->pUpsertTarget); + sqlite3ExprDelete(db, p->pUpsertTargetWhere); + sqlite3ExprListDelete(db, p->pUpsertSet); + sqlite3ExprDelete(db, p->pUpsertWhere); + sqlite3DbFree(db, p); + } +} + +/* +** Duplicate an Upsert object. +*/ +SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){ + if( p==0 ) return 0; + return sqlite3UpsertNew(db, + sqlite3ExprListDup(db, p->pUpsertTarget, 0), + sqlite3ExprDup(db, p->pUpsertTargetWhere, 0), + sqlite3ExprListDup(db, p->pUpsertSet, 0), + sqlite3ExprDup(db, p->pUpsertWhere, 0) + ); +} + +/* +** Create a new Upsert object. +*/ +SQLITE_PRIVATE Upsert *sqlite3UpsertNew( + sqlite3 *db, /* Determines which memory allocator to use */ + ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */ + Expr *pTargetWhere, /* Optional WHERE clause on the target */ + ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */ + Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */ +){ + Upsert *pNew; + pNew = sqlite3DbMallocRaw(db, sizeof(Upsert)); + if( pNew==0 ){ + sqlite3ExprListDelete(db, pTarget); + sqlite3ExprDelete(db, pTargetWhere); + sqlite3ExprListDelete(db, pSet); + sqlite3ExprDelete(db, pWhere); + return 0; + }else{ + pNew->pUpsertTarget = pTarget; + pNew->pUpsertTargetWhere = pTargetWhere; + pNew->pUpsertSet = pSet; + pNew->pUpsertWhere = pWhere; + pNew->pUpsertIdx = 0; + } + return pNew; +} + +/* +** Analyze the ON CONFLICT clause described by pUpsert. Resolve all +** symbols in the conflict-target. +** +** Return SQLITE_OK if everything works, or an error code is something +** is wrong. +*/ +SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( + Parse *pParse, /* The parsing context */ + SrcList *pTabList, /* Table into which we are inserting */ + Upsert *pUpsert /* The ON CONFLICT clauses */ +){ + Table *pTab; /* That table into which we are inserting */ + int rc; /* Result code */ + int iCursor; /* Cursor used by pTab */ + Index *pIdx; /* One of the indexes of pTab */ + ExprList *pTarget; /* The conflict-target clause */ + Expr *pTerm; /* One term of the conflict-target clause */ + NameContext sNC; /* Context for resolving symbolic names */ + Expr sCol[2]; /* Index column converted into an Expr */ + + assert( pTabList->nSrc==1 ); + assert( pTabList->a[0].pTab!=0 ); + assert( pUpsert!=0 ); + assert( pUpsert->pUpsertTarget!=0 ); + + /* Resolve all symbolic names in the conflict-target clause, which + ** includes both the list of columns and the optional partial-index + ** WHERE clause. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); + if( rc ) return rc; + rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); + if( rc ) return rc; + + /* Check to see if the conflict target matches the rowid. */ + pTab = pTabList->a[0].pTab; + pTarget = pUpsert->pUpsertTarget; + iCursor = pTabList->a[0].iCursor; + if( HasRowid(pTab) + && pTarget->nExpr==1 + && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN + && pTerm->iColumn==XN_ROWID + ){ + /* The conflict-target is the rowid of the primary table */ + assert( pUpsert->pUpsertIdx==0 ); + return SQLITE_OK; + } + + /* Initialize sCol[0..1] to be an expression parse tree for a + ** single column of an index. The sCol[0] node will be the TK_COLLATE + ** operator and sCol[1] will be the TK_COLUMN operator. Code below + ** will populate the specific collation and column number values + ** prior to comparing against the conflict-target expression. + */ + memset(sCol, 0, sizeof(sCol)); + sCol[0].op = TK_COLLATE; + sCol[0].pLeft = &sCol[1]; + sCol[1].op = TK_COLUMN; + sCol[1].iTable = pTabList->a[0].iCursor; + + /* Check for matches against other indexes */ + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int ii, jj, nn; + if( !IsUniqueIndex(pIdx) ) continue; + if( pTarget->nExpr!=pIdx->nKeyCol ) continue; + if( pIdx->pPartIdxWhere ){ + if( pUpsert->pUpsertTargetWhere==0 ) continue; + if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere, + pIdx->pPartIdxWhere, iCursor)!=0 ){ + continue; + } + } + nn = pIdx->nKeyCol; + for(ii=0; iiazColl[ii]; + if( pIdx->aiColumn[ii]==XN_EXPR ){ + assert( pIdx->aColExpr!=0 ); + assert( pIdx->aColExpr->nExpr>ii ); + pExpr = pIdx->aColExpr->a[ii].pExpr; + if( pExpr->op!=TK_COLLATE ){ + sCol[0].pLeft = pExpr; + pExpr = &sCol[0]; + } + }else{ + sCol[0].pLeft = &sCol[1]; + sCol[1].iColumn = pIdx->aiColumn[ii]; + pExpr = &sCol[0]; + } + for(jj=0; jja[jj].pExpr, pExpr,iCursor)<2 ){ + break; /* Column ii of the index matches column jj of target */ + } + } + if( jj>=nn ){ + /* The target contains no match for column jj of the index */ + break; + } + } + if( iipUpsertIdx = pIdx; + return SQLITE_OK; + } + sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any " + "PRIMARY KEY or UNIQUE constraint"); + return SQLITE_ERROR; +} + +/* +** Generate bytecode that does an UPDATE as part of an upsert. +** +** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK. +** In this case parameter iCur is a cursor open on the table b-tree that +** currently points to the conflicting table row. Otherwise, if pIdx +** is not NULL, then pIdx is the constraint that failed and iCur is a +** cursor points to the conflicting row. +*/ +SQLITE_PRIVATE void sqlite3UpsertDoUpdate( + Parse *pParse, /* The parsing and code-generating context */ + Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */ + Table *pTab, /* The table being updated */ + Index *pIdx, /* The UNIQUE constraint that failed */ + int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ +){ + Vdbe *v = pParse->pVdbe; + sqlite3 *db = pParse->db; + SrcList *pSrc; /* FROM clause for the UPDATE */ + int iDataCur = pUpsert->iDataCur; + + assert( v!=0 ); + VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); + if( pIdx && iCur!=iDataCur ){ + if( HasRowid(pTab) ){ + int regRowid = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); + sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, regRowid); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + int nPk = pPk->nKeyCol; + int iPk = pParse->nMem+1; + int i; + pParse->nMem += nPk; + for(i=0; iaiColumn[i]>=0 ); + k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); + sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); + VdbeComment((v, "%s.%s", pIdx->zName, + pTab->aCol[pPk->aiColumn[i]].zName)); + } + sqlite3VdbeVerifyAbortable(v, OE_Abort); + i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); + VdbeCoverage(v); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, + "corrupt database", P4_STATIC); + sqlite3VdbeJumpHere(v, i); + } + } + /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So + ** we have to make a copy before passing it down into sqlite3Update() */ + pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0); + sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet, + pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert); + pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */ + pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */ + VdbeNoopComment((v, "End DO UPDATE of UPSERT")); +} + +#endif /* SQLITE_OMIT_UPSERT */ + +/************** End of upsert.c **********************************************/ /************** Begin file vacuum.c ******************************************/ /* ** 2003 April 6 @@ -125978,8 +130241,14 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); - if( zSubSql ){ - assert( zSubSql[0]!='S' ); + /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, + ** or INSERT. Historically there have been attacks that first + ** corrupt the sqlite_master.sql field with other kinds of statements + ** then run VACUUM to get those statements to execute at inappropriate + ** times. */ + if( zSubSql + && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) + ){ rc = execSql(db, pzErrMsg, zSubSql); if( rc!=SQLITE_OK ) break; } @@ -126192,7 +130461,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = execSqlF(db, pzErrMsg, "SELECT sql FROM \"%w\".sqlite_master" - " WHERE type='index' AND length(sql)>10", + " WHERE type='index'", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; @@ -127362,9 +131631,6 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( void *pArg = 0; FuncDef *pNew; int rc = 0; - char *zLowerName; - unsigned char *z; - /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; @@ -127379,16 +131645,22 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( if( pMod->xFindFunction==0 ) return pDef; /* Call the xFindFunction method on the virtual table implementation - ** to see if the implementation wants to overload this function + ** to see if the implementation wants to overload this function. + ** + ** Though undocumented, we have historically always invoked xFindFunction + ** with an all lower-case function name. Continue in this tradition to + ** avoid any chance of an incompatibility. */ - zLowerName = sqlite3DbStrDup(db, pDef->zName); - if( zLowerName ){ - for(z=(unsigned char*)zLowerName; *z; z++){ - *z = sqlite3UpperToLower[*z]; +#ifdef SQLITE_DEBUG + { + int i; + for(i=0; pDef->zName[i]; i++){ + unsigned char x = (unsigned char)pDef->zName[i]; + assert( x==sqlite3UpperToLower[x] ); } - rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg); - sqlite3DbFree(db, zLowerName); } +#endif + rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg); if( rc==0 ){ return pDef; } @@ -127600,7 +131872,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) -/***/ int sqlite3WhereTrace; +/***/ extern int sqlite3WhereTrace; #endif #if defined(SQLITE_DEBUG) \ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) @@ -128048,12 +132320,10 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); #else -# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 +# define sqlite3WhereExplainOneScan(u,v,w,x) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3WhereAddScanStatus( @@ -128173,23 +132443,23 @@ static void explainAppendTerm( int i; assert( nTerm>=1 ); - if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); + if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); - if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); + if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); - sqlite3StrAccumAppend(pStr, zOp, 1); + sqlite3_str_append(pStr, zOp, 1); - if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); + if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); } /* @@ -128213,11 +132483,11 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ int i, j; if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; - sqlite3StrAccumAppend(pStr, " (", 2); + sqlite3_str_append(pStr, " (", 2); for(i=0; i=nSkip ? "%s=?" : "ANY(%s)", z); + if( i ) sqlite3_str_append(pStr, " AND ", 5); + sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); } j = i; @@ -128228,7 +132498,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } - sqlite3StrAccumAppend(pStr, ")", 1); + sqlite3_str_append(pStr, ")", 1); } /* @@ -128244,19 +132514,16 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ int ret = 0; #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pParse->explain==2 ) + if( sqlite3ParseToplevel(pParse)->explain==2 ) #endif { struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite3 *db = pParse->db; /* Database handle */ - int iId = pParse->iSelectId; /* Select id (left-most output column) */ int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ u32 flags; /* Flags that describe this loop */ @@ -128273,15 +132540,15 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); + sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ - sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); + sqlite3_str_appendf(&str, " SUBQUERY 0x%p", pItem->pSelect); }else{ - sqlite3XPrintf(&str, " TABLE %s", pItem->zName); + sqlite3_str_appendf(&str, " TABLE %s", pItem->zName); } if( pItem->zAlias ){ - sqlite3XPrintf(&str, " AS %s", pItem->zAlias); + sqlite3_str_appendf(&str, " AS %s", pItem->zAlias); } if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ const char *zFmt = 0; @@ -128304,8 +132571,8 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( zFmt = "INDEX %s"; } if( zFmt ){ - sqlite3StrAccumAppend(&str, " USING ", 7); - sqlite3XPrintf(&str, zFmt, pIdx->zName); + sqlite3_str_append(&str, " USING ", 7); + sqlite3_str_appendf(&str, zFmt, pIdx->zName); explainIndexRange(&str, pLoop); } }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ @@ -128320,23 +132587,26 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( assert( flags&WHERE_TOP_LIMIT); zRangeOp = "<"; } - sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + sqlite3_str_appendf(&str, + " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", + sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s", pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS if( pLoop->nOut>=10 ){ - sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); + sqlite3_str_appendf(&str, " (~%llu rows)", + sqlite3LogEstToInt(pLoop->nOut)); }else{ - sqlite3StrAccumAppend(&str, " (~1 row)", 9); + sqlite3_str_append(&str, " (~1 row)", 9); } #endif zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); + ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), + pParse->addrExplain, 0, zMsg,P4_DYNAMIC); } return ret; } @@ -128416,8 +132686,8 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ int nLoop = 0; - while( ALWAYS(pTerm!=0) - && (pTerm->wtFlags & TERM_CODED)==0 + assert( pTerm!=0 ); + while( (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ @@ -128428,6 +132698,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ } if( pTerm->iParent<0 ) break; pTerm = &pTerm->pWC->a[pTerm->iParent]; + assert( pTerm!=0 ); pTerm->nChild--; if( pTerm->nChild!=0 ) break; nLoop++; @@ -128498,6 +132769,102 @@ static void updateRangeAffinityStr( } } + +/* +** pX is an expression of the form: (vector) IN (SELECT ...) +** In other words, it is a vector IN operator with a SELECT clause on the +** LHS. But not all terms in the vector are indexable and the terms might +** not be in the correct order for indexing. +** +** This routine makes a copy of the input pX expression and then adjusts +** the vector on the LHS with corresponding changes to the SELECT so that +** the vector contains only index terms and those terms are in the correct +** order. The modified IN expression is returned. The caller is responsible +** for deleting the returned expression. +** +** Example: +** +** CREATE TABLE t1(a,b,c,d,e,f); +** CREATE INDEX t1x1 ON t1(e,c); +** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2) +** \_______________________________________/ +** The pX expression +** +** Since only columns e and c can be used with the index, in that order, +** the modified IN expression that is returned will be: +** +** (e,c) IN (SELECT z,x FROM t2) +** +** The reduced pX is different from the original (obviously) and thus is +** only used for indexing, to improve performance. The original unaltered +** IN expression must also be run on each output row for correctness. +*/ +static Expr *removeUnindexableInClauseTerms( + Parse *pParse, /* The parsing context */ + int iEq, /* Look at loop terms starting here */ + WhereLoop *pLoop, /* The current loop */ + Expr *pX /* The IN expression to be reduced */ +){ + sqlite3 *db = pParse->db; + Expr *pNew = sqlite3ExprDup(db, pX, 0); + if( db->mallocFailed==0 ){ + ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */ + ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */ + ExprList *pRhs = 0; /* New RHS after modifications */ + ExprList *pLhs = 0; /* New LHS after mods */ + int i; /* Loop counter */ + Select *pSelect; /* Pointer to the SELECT on the RHS */ + + for(i=iEq; inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iField = pLoop->aLTerm[i]->iField - 1; + assert( pOrigRhs->a[iField].pExpr!=0 ); + pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); + pOrigRhs->a[iField].pExpr = 0; + assert( pOrigLhs->a[iField].pExpr!=0 ); + pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr); + pOrigLhs->a[iField].pExpr = 0; + } + } + sqlite3ExprListDelete(db, pOrigRhs); + sqlite3ExprListDelete(db, pOrigLhs); + pNew->pLeft->x.pList = pLhs; + pNew->x.pSelect->pEList = pRhs; + if( pLhs && pLhs->nExpr==1 ){ + /* Take care here not to generate a TK_VECTOR containing only a + ** single value. Since the parser never creates such a vector, some + ** of the subroutines do not handle this case. */ + Expr *p = pLhs->a[0].pExpr; + pLhs->a[0].pExpr = 0; + sqlite3ExprDelete(db, pNew->pLeft); + pNew->pLeft = p; + } + pSelect = pNew->x.pSelect; + if( pSelect->pOrderBy ){ + /* If the SELECT statement has an ORDER BY clause, zero the + ** iOrderByCol variables. These are set to non-zero when an + ** ORDER BY term exactly matches one of the terms of the + ** result-set. Since the result-set of the SELECT statement may + ** have been modified or reordered, these variables are no longer + ** set correctly. Since setting them is just an optimization, + ** it's easiest just to zero them here. */ + ExprList *pOrderBy = pSelect->pOrderBy; + for(i=0; inExpr; i++){ + pOrderBy->a[i].u.x.iOrderByCol = 0; + } + } + +#if 0 + printf("For indexing, change the IN expr:\n"); + sqlite3TreeViewExpr(0, pX, 0); + printf("Into:\n"); + sqlite3TreeViewExpr(0, pNew, 0); +#endif + } + return pNew; +} + + /* ** Generate code for a single equality term of the WHERE clause. An equality ** term can be either X=expr or X IN (...). pTerm is the term to be @@ -128560,68 +132927,23 @@ static int codeEqualityTerm( } } for(i=iEq;inLTerm; i++){ - if( ALWAYS(pLoop->aLTerm[i]) && pLoop->aLTerm[i]->pExpr==pX ) nEq++; + assert( pLoop->aLTerm[i]!=0 ); + if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; } if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); }else{ - Select *pSelect = pX->x.pSelect; sqlite3 *db = pParse->db; - u16 savedDbOptFlags = db->dbOptFlags; - ExprList *pOrigRhs = pSelect->pEList; - ExprList *pOrigLhs = pX->pLeft->x.pList; - ExprList *pRhs = 0; /* New Select.pEList for RHS */ - ExprList *pLhs = 0; /* New pX->pLeft vector */ + pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); - for(i=iEq;inLTerm; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - int iField = pLoop->aLTerm[i]->iField - 1; - Expr *pNewRhs = sqlite3ExprDup(db, pOrigRhs->a[iField].pExpr, 0); - Expr *pNewLhs = sqlite3ExprDup(db, pOrigLhs->a[iField].pExpr, 0); - - pRhs = sqlite3ExprListAppend(pParse, pRhs, pNewRhs); - pLhs = sqlite3ExprListAppend(pParse, pLhs, pNewLhs); - } - } if( !db->mallocFailed ){ - Expr *pLeft = pX->pLeft; - - if( pSelect->pOrderBy ){ - /* If the SELECT statement has an ORDER BY clause, zero the - ** iOrderByCol variables. These are set to non-zero when an - ** ORDER BY term exactly matches one of the terms of the - ** result-set. Since the result-set of the SELECT statement may - ** have been modified or reordered, these variables are no longer - ** set correctly. Since setting them is just an optimization, - ** it's easiest just to zero them here. */ - ExprList *pOrderBy = pSelect->pOrderBy; - for(i=0; inExpr; i++){ - pOrderBy->a[i].u.x.iOrderByCol = 0; - } - } - - /* Take care here not to generate a TK_VECTOR containing only a - ** single value. Since the parser never creates such a vector, some - ** of the subroutines do not handle this case. */ - if( pLhs->nExpr==1 ){ - pX->pLeft = pLhs->a[0].pExpr; - }else{ - pLeft->x.pList = pLhs; - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); - testcase( aiMap==0 ); - } - pSelect->pEList = pRhs; - db->dbOptFlags |= SQLITE_QueryFlattener; + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); - db->dbOptFlags = savedDbOptFlags; - testcase( aiMap!=0 && aiMap[0]!=0 ); - pSelect->pEList = pOrigRhs; - pLeft->x.pList = pOrigLhs; - pX->pLeft = pLeft; + pTerm->pExpr->iTable = pX->iTable; } - sqlite3ExprListDelete(pParse->db, pLhs); - sqlite3ExprListDelete(pParse->db, pRhs); + sqlite3ExprDelete(db, pX); + pX = pTerm->pExpr; } if( eType==IN_INDEX_INDEX_DESC ){ @@ -129285,6 +133607,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ + assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) + || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 + ); if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); @@ -129465,7 +133790,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( sqlite3ExprIsVector(pX->pRight) ){ r1 = rTemp = sqlite3GetTempReg(pParse); codeExprOrVector(pParse, pX->pRight, r1, 1); - op = aMoveOp[(pX->op - TK_GT) | 0x0001]; + testcase( pX->op==TK_GT ); + testcase( pX->op==TK_GE ); + testcase( pX->op==TK_LT ); + testcase( pX->op==TK_LE ); + op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; + assert( pX->op!=TK_GT || op==OP_SeekGE ); + assert( pX->op!=TK_GE || op==OP_SeekGE ); + assert( pX->op!=TK_LT || op==OP_SeekLE ); + assert( pX->op!=TK_LE || op==OP_SeekLE ); }else{ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); disableTerm(pLevel, pStart); @@ -129760,6 +134093,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } }else if( bStopAtNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); endEq = 0; nConstraint++; } @@ -129809,9 +134143,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* If pIdx is an index on one or more expressions, then look through ** all the expressions in pWInfo and try to transform matching expressions ** into reference to index columns. + ** + ** Do not do this for the RHS of a LEFT JOIN. This is because the + ** expression may be evaluated after OP_NullRow has been executed on + ** the cursor. In this case it is important to do the full evaluation, + ** as the result of the expression may not be NULL, even if all table + ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a */ - whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); - + if( pLevel->iLeftJoin==0 ){ + whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); + } /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){ @@ -129967,7 +134308,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( for(iTerm=0; iTermnTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; - if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; @@ -129986,13 +134326,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); + ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ int jmp1 = 0; /* Address of jump operation */ - if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ + assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 + || ExprHasProperty(pOrExpr, EP_FromJoin) + ); + if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } @@ -130004,7 +134348,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = sqlite3WhereExplainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 + pParse, pOrTab, &pSubWInfo->a[0], 0 ); sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); @@ -130103,6 +134447,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } } } + ExplainQueryPlanPop(pParse); pLevel->u.pCovidx = pCov; if( pCov ) pLevel->iIdxCur = iCovCur; if( pAndExpr ){ @@ -130175,7 +134520,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } pE = pTerm->pExpr; assert( pE!=0 ); - if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ + if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){ continue; } @@ -130188,7 +134533,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( continue; } - if( pTerm->wtFlags & TERM_LIKECOND ){ + if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){ /* If the TERM_LIKECOND flag is set, that means that the range search ** is sufficient to guarantee that the LIKE operator is true, so we ** can skip the call to the like(A,B) function. But this only works @@ -130198,8 +134543,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( continue; #else u32 x = pLevel->iLikeRepCntr; - assert( x>0 ); - skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1)); + if( x>0 ){ + skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); + } VdbeCoverage(v); #endif } @@ -130239,6 +134585,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( WO_EQ|WO_IN|WO_IS, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; + if( (pAlt->eOperator & WO_IN) + && (pAlt->pExpr->flags & EP_xIsSelect) + && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) + ){ + continue; + } testcase( pAlt->eOperator & WO_EQ ); testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); @@ -131095,7 +135447,6 @@ static void exprAnalyzeOrTerm( }else{ sqlite3ExprListDelete(db, pList); } - pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ } } } @@ -131153,6 +135504,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ for(i=0; inSrc; i++){ mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); + if( pSrc->a[i].fg.isTabFunc ){ + mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); + } } } pS = pS->pPrior; @@ -131260,7 +135614,7 @@ static void exprAnalyze( int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection */ - unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ + unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */ int nLeft; /* Number of elements on left side vector */ if( db->mallocFailed ){ @@ -131504,7 +135858,7 @@ static void exprAnalyze( ** to do anything with MATCH functions. */ if( pWC->op==TK_AND ){ - Expr *pRight, *pLeft; + Expr *pRight = 0, *pLeft = 0; int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); while( res-- > 0 ){ int idxNew; @@ -131565,7 +135919,7 @@ static void exprAnalyze( exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ pTerm->eOperator = 0; } @@ -131828,6 +136182,21 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( /* #include "sqliteInt.h" */ /* #include "whereInt.h" */ +/* +** Extra information appended to the end of sqlite3_index_info but not +** visible to the xBestIndex function, at least not directly. The +** sqlite3_vtab_collation() interface knows how to reach it, however. +** +** This object is not an API and can be changed from one release to the +** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() +** agree on the structure, all will be well. +*/ +typedef struct HiddenIndexInfo HiddenIndexInfo; +struct HiddenIndexInfo { + WhereClause *pWC; /* The Where clause being analyzed */ + Parse *pParse; /* The parsing context */ +}; + /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); @@ -132650,11 +137019,11 @@ end_auto_index_create: ** by passing the pointer returned by this function to sqlite3_free(). */ static sqlite3_index_info *allocateIndexInfo( - Parse *pParse, - WhereClause *pWC, + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause being analyzed */ Bitmask mUnusable, /* Ignore terms with these prereqs */ - struct SrcList_item *pSrc, - ExprList *pOrderBy, + struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */ + ExprList *pOrderBy, /* The ORDER BY clause */ u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; @@ -132662,6 +137031,7 @@ static sqlite3_index_info *allocateIndexInfo( struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; + struct HiddenIndexInfo *pHidden; WhereTerm *pTerm; int nOrderBy; sqlite3_index_info *pIdxInfo; @@ -132703,7 +137073,7 @@ static sqlite3_index_info *allocateIndexInfo( */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy ); + + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) ); if( pIdxInfo==0 ){ sqlite3ErrorMsg(pParse, "out of memory"); return 0; @@ -132714,7 +137084,8 @@ static sqlite3_index_info *allocateIndexInfo( ** changing them. We have to do some funky casting in order to ** initialize those fields. */ - pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; + pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; + pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; *(int*)&pIdxInfo->nConstraint = nTerm; @@ -132724,6 +137095,8 @@ static sqlite3_index_info *allocateIndexInfo( *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = pUsage; + pHidden->pWC = pWC; + pHidden->pParse = pParse; for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ u16 op; if( pTerm->leftCursor != pSrc->iCursor ) continue; @@ -133672,22 +138045,21 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ ** Free a WhereInfo structure */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - if( ALWAYS(pWInfo) ){ - int i; - for(i=0; inLevel; i++){ - WhereLevel *pLevel = &pWInfo->a[i]; - if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ - sqlite3DbFree(db, pLevel->u.in.aInLoop); - } + int i; + assert( pWInfo!=0 ); + for(i=0; inLevel; i++){ + WhereLevel *pLevel = &pWInfo->a[i]; + if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ + sqlite3DbFree(db, pLevel->u.in.aInLoop); } - sqlite3WhereClauseClear(&pWInfo->sWC); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - sqlite3DbFreeNN(db, pWInfo); } + sqlite3WhereClauseClear(&pWInfo->sWC); + while( pWInfo->pLoops ){ + WhereLoop *p = pWInfo->pLoops; + pWInfo->pLoops = p->pNextLoop; + whereLoopDelete(db, p); + } + sqlite3DbFreeNN(db, pWInfo); } /* @@ -134164,8 +138536,8 @@ static int whereLoopAddBtreeIndex( pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; - WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", - pProbe->zName, pNew->u.btree.nEq)); + WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n", + pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq)); assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); @@ -134211,15 +138583,12 @@ static int whereLoopAddBtreeIndex( ** to mix with a lower range bound from some other source */ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; - /* Do not allow IS constraints from the WHERE clause to be used by the + /* Do not allow constraints from the WHERE clause to be used by the ** right table of a LEFT JOIN. Only constraints in the ON clause are ** allowed */ if( (pSrc->fg.jointype & JT_LEFT)!=0 && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - && (eOp & (WO_IS|WO_ISNULL))!=0 ){ - testcase( eOp & WO_IS ); - testcase( eOp & WO_ISNULL ); continue; } @@ -134270,12 +138639,14 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_EQ; assert( saved_nEq==pNew->u.btree.nEq ); if( iCol==XN_ROWID - || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) + || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ - if( iCol>=0 && pProbe->uniqNotNull==0 ){ - pNew->wsFlags |= WHERE_UNQ_WANTED; - }else{ + if( iCol==XN_ROWID || pProbe->uniqNotNull + || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) + ){ pNew->wsFlags |= WHERE_ONEROW; + }else{ + pNew->wsFlags |= WHERE_UNQ_WANTED; } } }else if( eOp & WO_ISNULL ){ @@ -134449,8 +138820,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; } - WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", - pProbe->zName, saved_nEq, rc)); + WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); return rc; } @@ -134654,14 +139025,16 @@ static int whereLoopAddBtree( /* TUNING: One-time cost for computing the automatic index is ** estimated to be X*N*log2(N) where N is the number of rows in ** the table being indexed and where X is 7 (LogEst=28) for normal - ** tables or 1.375 (LogEst=4) for views and subqueries. The value + ** tables or 0.5 (LogEst=-10) for views and subqueries. The value ** of X is smaller for views and subqueries so that the query planner ** will be more aggressive about generating automatic indexes for ** those objects, since there is no opportunity to add schema ** indexes on subqueries and views. */ - pNew->rSetup = rLogSize + rSize + 4; + pNew->rSetup = rLogSize + rSize; if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ - pNew->rSetup += 24; + pNew->rSetup += 28; + }else{ + pNew->rSetup -= 10; } ApplyCostMultiplier(pNew->rSetup, pTab->costMult); if( pNew->rSetup<0 ) pNew->rSetup = 0; @@ -134679,14 +139052,17 @@ static int whereLoopAddBtree( } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - /* Loop over all indices - */ - for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ + /* Loop over all indices. If there was an INDEXED BY clause, then only + ** consider index pProbe. */ + for(; rc==SQLITE_OK && pProbe; + pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++ + ){ if( pProbe->pPartIdxWhere!=0 && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){ testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ continue; /* Partial index inappropriate for this query */ } + if( pProbe->bNoQuery ) continue; rSize = pProbe->aiRowLogEst[0]; pNew->u.btree.nEq = 0; pNew->u.btree.nBtm = 0; @@ -134791,10 +139167,6 @@ static int whereLoopAddBtree( pBuilder->nRecValid = 0; pBuilder->pRec = 0; #endif - - /* If there was an INDEXED BY clause, then only that one index is - ** considered. */ - if( pSrc->pIBIndex ) break; } return rc; } @@ -134889,9 +139261,9 @@ static int whereLoopAddVirtualOne( || pNew->aLTerm[iTerm]!=0 || pIdxCons->usable==0 ){ - rc = SQLITE_ERROR; sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); - return rc; + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; } testcase( iTerm==nConstraint-1 ); testcase( j==0 ); @@ -134919,6 +139291,15 @@ static int whereLoopAddVirtualOne( pNew->u.vtab.omitMask &= ~mNoOmit; pNew->nLTerm = mxTerm+1; + for(i=0; i<=mxTerm; i++){ + if( pNew->aLTerm[i]==0 ){ + /* The non-zero argvIdx values must be contiguous. Raise an + ** error if they are not */ + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; + } + } assert( pNew->nLTerm<=pNew->nLSlot ); pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; @@ -134949,6 +139330,27 @@ static int whereLoopAddVirtualOne( return rc; } +/* +** If this function is invoked from within an xBestIndex() callback, it +** returns a pointer to a buffer containing the name of the collation +** sequence associated with element iCons of the sqlite3_index_info.aConstraint +** array. Or, if iCons is out of range or there is no active xBestIndex +** call, return NULL. +*/ +SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + const char *zRet = 0; + if( iCons>=0 && iConsnConstraint ){ + CollSeq *pC = 0; + int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; + Expr *pX = pHidden->pWC->a[iTerm].pExpr; + if( pX->pLeft ){ + pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight); + } + zRet = (pC ? pC->zName : "BINARY"); + } + return zRet; +} /* ** Add all WhereLoop objects for a table of the join identified by @@ -135013,6 +139415,7 @@ static int whereLoopAddVirtual( } /* First call xBestIndex() with all constraints usable. */ + WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); WHERETRACE(0x40, (" VirtualOne: all usable\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); @@ -135088,6 +139491,7 @@ static int whereLoopAddVirtual( if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); sqlite3DbFreeNN(pParse->db, p); + WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -135766,12 +140170,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){ + if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ /* Do not use an automatic index if the this loop is expected - ** to run less than 2 times. */ + ** to run less than 1.25 times. It is tempting to also exclude + ** automatic index usage on an outer loop, but sometimes an automatic + ** index is useful in the outer loop of a correlated subquery. */ assert( 10==sqlite3LogEst(2) ); continue; } + /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); @@ -136353,6 +140760,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** @@ -136402,6 +140810,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ for(ii=0; iinTerm; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; + if( pT->wtFlags & TERM_VIRTUAL ) continue; if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); pT->wtFlags |= TERM_CODED; @@ -136489,35 +140898,80 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } } #endif - /* Attempt to omit tables from the join that do not effect the result */ + + /* Attempt to omit tables from the join that do not affect the result. + ** For a table to not affect the result, the following must be true: + ** + ** 1) The query must not be an aggregate. + ** 2) The table must be the RHS of a LEFT JOIN. + ** 3) Either the query must be DISTINCT, or else the ON or USING clause + ** must contain a constraint that limits the scan of the table to + ** at most a single row. + ** 4) The table must not be referenced by any part of the query apart + ** from its own USING or ON clause. + ** + ** For example, given: + ** + ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); + ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); + ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); + ** + ** then table t2 can be omitted from the following: + ** + ** SELECT v1, v3 FROM t1 + ** LEFT JOIN t2 USING (t1.ipk=t2.ipk) + ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) + ** + ** or from: + ** + ** SELECT DISTINCT v1, v3 FROM t1 + ** LEFT JOIN t2 + ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) + */ + notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 - && pResultSet!=0 + && pResultSet!=0 /* guarantees condition (1) above */ && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ + int i; Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); if( sWLB.pOrderBy ){ tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); } - while( pWInfo->nLevel>=2 ){ + for(i=pWInfo->nLevel-1; i>=1; i--){ WhereTerm *pTerm, *pEnd; - pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; - if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break; + struct SrcList_item *pItem; + pLoop = pWInfo->a[i].pWLoop; + pItem = &pWInfo->pTabList->a[pLoop->iTab]; + if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 && (pLoop->wsFlags & WHERE_ONEROW)==0 ){ - break; + continue; } - if( (tabUsed & pLoop->maskSelf)!=0 ) break; + if( (tabUsed & pLoop->maskSelf)!=0 ) continue; pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - break; + if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){ + if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + || pTerm->pExpr->iRightJoinTable!=pItem->iCursor + ){ + break; + } } } - if( pTerm drop loop %c not used\n", pLoop->cId)); + notReady &= ~pLoop->maskSelf; + for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ + pTerm->wtFlags |= TERM_CODED; + } + } + if( i!=pWInfo->nLevel-1 ){ + int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); + memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); + } pWInfo->nLevel--; nTabList--; } @@ -136527,15 +140981,32 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. + ** + ** A one-pass approach can be used if the caller has requested one + ** and either (a) the scan visits at most one row or (b) each + ** of the following are true: + ** + ** * the caller has indicated that a one-pass approach can be used + ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and + ** * the table is not a virtual table, and + ** * either the scan does not use the OR optimization or the caller + ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified + ** for DELETE). + ** + ** The last qualification is because an UPDATE statement uses + ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can + ** use a one-pass approach, and this is not set accurately for scans + ** that use the OR optimization. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ int wsFlags = pWInfo->a[0].pWLoop->wsFlags; int bOnerow = (wsFlags & WHERE_ONEROW)!=0; - if( bOnerow - || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 - && 0==(wsFlags & WHERE_VIRTUALTABLE)) - ){ + if( bOnerow || ( + 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) + && 0==(wsFlags & WHERE_VIRTUALTABLE) + && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) + )){ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ @@ -136672,7 +141143,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** loop below generates code for a single nested loop of the VM ** program. */ - notReady = ~(Bitmask)0; for(ii=0; iiiFrom, wctrlFlags + pParse, pTabList, pLevel, wctrlFlags ); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); @@ -136736,6 +141206,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ Index *pIdx; int n; if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED + && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ && (pLoop->wsFlags & WHERE_INDEXED)!=0 && (pIdx = pLoop->u.btree.pIndex)->hasStat1 && (n = pLoop->u.btree.nIdxCol)>0 @@ -136802,7 +141273,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); + assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); } if( (ws & WHERE_INDEXED) || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) @@ -136871,7 +141343,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp = sqlite3VdbeGetOp(v, k); for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column ){ + if( pOp->opcode==OP_Column +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + || pOp->opcode==OP_Offset +#endif + ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); if( !HasRowid(pTab) ){ @@ -136970,15 +141446,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ */ #define YYMALLOCARGTYPE u64 -/* -** An instance of this structure holds information about the -** LIMIT clause of a SELECT statement. -*/ -struct LimitVal { - Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ - Expr *pOffset; /* The OFFSET expression. NULL if there is none */ -}; - /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, @@ -137022,20 +141489,12 @@ static void disableLookaside(Parse *pParse){ } } - /* This is a utility routine used to set the ExprSpan.zStart and - ** ExprSpan.zEnd values of pOut so that the span covers the complete - ** range of text beginning with pStart and going to the end of pEnd. - */ - static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ - pOut->zStart = pStart->z; - pOut->zEnd = &pEnd->z[pEnd->n]; - } /* Construct a new Expr object from a single identifier. Use the ** new Expr to populate pOut. Set the span of pOut to be the identifier ** that created the expression. */ - static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ + static Expr *tokenExpr(Parse *pParse, int op, Token t){ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ memset(p, 0, sizeof(Expr)); @@ -137053,45 +141512,9 @@ static void disableLookaside(Parse *pParse){ p->nHeight = 1; #endif } - pOut->pExpr = p; - pOut->zStart = t.z; - pOut->zEnd = &t.z[t.n]; + return p; } - /* This routine constructs a binary expression node out of two ExprSpan - ** objects and uses the result to populate a new ExprSpan object. - */ - static void spanBinaryExpr( - Parse *pParse, /* The parsing context. Errors accumulate here */ - int op, /* The binary operation */ - ExprSpan *pLeft, /* The left operand, and output */ - ExprSpan *pRight /* The right operand */ - ){ - pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); - pLeft->zEnd = pRight->zEnd; - } - - /* If doNot is true, then add a TK_NOT Expr-node wrapper around the - ** outside of *ppExpr. - */ - static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ - if( doNot ){ - pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); - } - } - - /* Construct an expression node for a unary postfix operator - */ - static void spanUnaryPostfix( - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand, and output */ - Token *pPostOp /* The operand token for setting the span */ - ){ - pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); - pOperand->zEnd = &pPostOp->z[pPostOp->n]; - } - /* A routine to convert a binary TK_IS or TK_ISNOT expression into a ** unary TK_ISNULL or TK_NOTNULL expression. */ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ @@ -137103,20 +141526,6 @@ static void disableLookaside(Parse *pParse){ } } - /* Construct an expression node for a unary prefix operator - */ - static void spanUnaryPrefix( - ExprSpan *pOut, /* Write the new expression node here */ - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand */ - Token *pPreOp /* The operand token for setting the span */ - ){ - pOut->zStart = pPreOp->z; - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); - pOut->zEnd = pOperand->zEnd; - } - /* Add a single new term to an ExprList that is used to store a ** list of identifiers. Report an error if the ID list contains ** a COLLATE clause or an ASC or DESC keyword, except ignore the @@ -137179,64 +141588,74 @@ static void disableLookaside(Parse *pParse){ ** zero the stack is dynamically sized using realloc() ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument +** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser +** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar +** YYNTOKEN Number of terminal symbols ** YY_MAX_SHIFT Maximum value for shift actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_MIN_REDUCE Minimum value for reduce actions -** YY_MAX_REDUCE Maximum value for reduce actions ** YY_ERROR_ACTION The yy_action[] code for syntax error ** YY_ACCEPT_ACTION The yy_action[] code for accept ** YY_NO_ACTION The yy_action[] code for no-op +** YY_MIN_REDUCE Minimum value for reduce actions +** YY_MAX_REDUCE Maximum value for reduce actions */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned char -#define YYNOCODE 252 +#define YYNOCODE 255 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 83 +#define YYWILDCARD 84 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - Expr* yy72; - TriggerStep* yy145; - ExprList* yy148; - SrcList* yy185; - ExprSpan yy190; - int yy194; - Select* yy243; - IdList* yy254; - With* yy285; - struct TrigEvent yy332; - struct LimitVal yy354; - struct {int value; int mask;} yy497; + const char* yy36; + TriggerStep* yy47; + With* yy91; + struct {int value; int mask;} yy107; + Expr* yy182; + Upsert* yy198; + ExprList* yy232; + struct TrigEvent yy300; + Select* yy399; + SrcList* yy427; + int yy502; + IdList* yy510; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif -#define sqlite3ParserARG_SDECL Parse *pParse; -#define sqlite3ParserARG_PDECL ,Parse *pParse -#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse -#define sqlite3ParserARG_STORE yypParser->pParse = pParse +#define sqlite3ParserARG_SDECL +#define sqlite3ParserARG_PDECL +#define sqlite3ParserARG_PARAM +#define sqlite3ParserARG_FETCH +#define sqlite3ParserARG_STORE +#define sqlite3ParserCTX_SDECL Parse *pParse; +#define sqlite3ParserCTX_PDECL ,Parse *pParse +#define sqlite3ParserCTX_PARAM ,pParse +#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; +#define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 -#define YYNSTATE 455 -#define YYNRULE 329 -#define YY_MAX_SHIFT 454 -#define YY_MIN_SHIFTREDUCE 664 -#define YY_MAX_SHIFTREDUCE 992 -#define YY_MIN_REDUCE 993 -#define YY_MAX_REDUCE 1321 -#define YY_ERROR_ACTION 1322 -#define YY_ACCEPT_ACTION 1323 -#define YY_NO_ACTION 1324 +#define YYNSTATE 490 +#define YYNRULE 341 +#define YYNTOKEN 145 +#define YY_MAX_SHIFT 489 +#define YY_MIN_SHIFTREDUCE 705 +#define YY_MAX_SHIFTREDUCE 1045 +#define YY_ERROR_ACTION 1046 +#define YY_ACCEPT_ACTION 1047 +#define YY_NO_ACTION 1048 +#define YY_MIN_REDUCE 1049 +#define YY_MAX_REDUCE 1389 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -137266,9 +141685,6 @@ typedef union { ** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then ** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. ** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE -** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. @@ -137276,25 +141692,22 @@ typedef union { ** N == YY_NO_ACTION No such action. Denotes unused ** slots in the yy_action[] table. ** +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +** and YY_MAX_REDUCE +** ** The action table is constructed as a single large table named yy_action[]. ** Given state S and lookahead X, the action is computed as either: ** ** (A) N = yy_action[ yy_shift_ofst[S] + X ] ** (B) N = yy_default[S] ** -** The (A) formula is preferred. The B formula is used instead if: -** (1) The yy_shift_ofst[S]+X value is out of range, or -** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or -** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. -** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that -** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. -** Hence only tests (1) and (2) need to be evaluated.) +** The (A) formula is preferred. The B formula is used instead if +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. ** ** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of -** YY_SHIFT_USE_DFLT. +** the yy_shift_ofst[] array. ** ** The following are the tables generated in this section: ** @@ -137308,463 +141721,503 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (1566) +#define YY_ACTTAB_COUNT (1657) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 324, 1323, 155, 155, 2, 203, 94, 94, 94, 93, - /* 10 */ 350, 98, 98, 98, 98, 91, 95, 95, 94, 94, - /* 20 */ 94, 93, 350, 268, 99, 100, 90, 971, 971, 847, - /* 30 */ 850, 839, 839, 97, 97, 98, 98, 98, 98, 350, - /* 40 */ 969, 96, 96, 96, 96, 95, 95, 94, 94, 94, - /* 50 */ 93, 350, 950, 96, 96, 96, 96, 95, 95, 94, - /* 60 */ 94, 94, 93, 350, 250, 96, 96, 96, 96, 95, - /* 70 */ 95, 94, 94, 94, 93, 350, 224, 224, 969, 132, - /* 80 */ 888, 348, 347, 415, 172, 324, 1286, 449, 414, 950, - /* 90 */ 951, 952, 808, 977, 1032, 950, 300, 786, 428, 132, - /* 100 */ 975, 362, 976, 9, 9, 787, 132, 52, 52, 99, - /* 110 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, - /* 120 */ 98, 98, 98, 98, 372, 978, 241, 978, 262, 369, - /* 130 */ 261, 120, 950, 951, 952, 194, 58, 324, 401, 398, - /* 140 */ 397, 808, 427, 429, 75, 808, 1260, 1260, 132, 396, - /* 150 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 160 */ 350, 99, 100, 90, 971, 971, 847, 850, 839, 839, - /* 170 */ 97, 97, 98, 98, 98, 98, 786, 262, 369, 261, - /* 180 */ 826, 262, 364, 251, 787, 1084, 101, 1114, 72, 324, - /* 190 */ 227, 1113, 242, 411, 442, 819, 92, 89, 178, 818, - /* 200 */ 1022, 268, 96, 96, 96, 96, 95, 95, 94, 94, - /* 210 */ 94, 93, 350, 99, 100, 90, 971, 971, 847, 850, - /* 220 */ 839, 839, 97, 97, 98, 98, 98, 98, 449, 372, - /* 230 */ 818, 818, 820, 92, 89, 178, 60, 92, 89, 178, - /* 240 */ 1025, 324, 357, 930, 1316, 300, 61, 1316, 52, 52, - /* 250 */ 836, 836, 848, 851, 96, 96, 96, 96, 95, 95, - /* 260 */ 94, 94, 94, 93, 350, 99, 100, 90, 971, 971, - /* 270 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, - /* 280 */ 92, 89, 178, 427, 412, 198, 930, 1317, 454, 995, - /* 290 */ 1317, 355, 1024, 324, 243, 231, 114, 277, 348, 347, - /* 300 */ 1242, 950, 416, 1071, 928, 840, 96, 96, 96, 96, - /* 310 */ 95, 95, 94, 94, 94, 93, 350, 99, 100, 90, - /* 320 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, - /* 330 */ 98, 98, 449, 328, 449, 120, 23, 256, 950, 951, - /* 340 */ 952, 968, 978, 438, 978, 324, 329, 928, 954, 701, - /* 350 */ 200, 175, 52, 52, 52, 52, 939, 353, 96, 96, - /* 360 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 99, - /* 370 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, - /* 380 */ 98, 98, 98, 98, 354, 449, 954, 427, 417, 427, - /* 390 */ 426, 1290, 92, 89, 178, 268, 253, 324, 255, 1058, - /* 400 */ 1037, 694, 93, 350, 383, 52, 52, 380, 1058, 374, - /* 410 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 420 */ 350, 99, 100, 90, 971, 971, 847, 850, 839, 839, - /* 430 */ 97, 97, 98, 98, 98, 98, 228, 449, 167, 449, - /* 440 */ 427, 407, 157, 446, 446, 446, 349, 349, 349, 324, - /* 450 */ 310, 316, 991, 827, 320, 242, 411, 51, 51, 36, - /* 460 */ 36, 254, 96, 96, 96, 96, 95, 95, 94, 94, - /* 470 */ 94, 93, 350, 99, 100, 90, 971, 971, 847, 850, - /* 480 */ 839, 839, 97, 97, 98, 98, 98, 98, 194, 316, - /* 490 */ 929, 401, 398, 397, 224, 224, 1265, 939, 353, 1318, - /* 500 */ 317, 324, 396, 1063, 1063, 813, 414, 1061, 1061, 950, - /* 510 */ 299, 448, 992, 268, 96, 96, 96, 96, 95, 95, - /* 520 */ 94, 94, 94, 93, 350, 99, 100, 90, 971, 971, - /* 530 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, - /* 540 */ 757, 1041, 449, 893, 893, 386, 950, 951, 952, 410, - /* 550 */ 992, 747, 747, 324, 229, 268, 221, 296, 268, 771, - /* 560 */ 890, 378, 52, 52, 890, 421, 96, 96, 96, 96, - /* 570 */ 95, 95, 94, 94, 94, 93, 350, 99, 100, 90, - /* 580 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, - /* 590 */ 98, 98, 103, 449, 275, 384, 1241, 343, 157, 1207, - /* 600 */ 909, 669, 670, 671, 176, 197, 196, 195, 324, 298, - /* 610 */ 319, 1266, 2, 37, 37, 910, 1134, 1040, 96, 96, - /* 620 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 697, - /* 630 */ 911, 177, 99, 100, 90, 971, 971, 847, 850, 839, - /* 640 */ 839, 97, 97, 98, 98, 98, 98, 230, 146, 120, - /* 650 */ 735, 1235, 826, 270, 1141, 273, 1141, 771, 171, 170, - /* 660 */ 736, 1141, 82, 324, 80, 268, 697, 819, 158, 268, - /* 670 */ 378, 818, 78, 96, 96, 96, 96, 95, 95, 94, - /* 680 */ 94, 94, 93, 350, 120, 950, 393, 99, 100, 90, - /* 690 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, - /* 700 */ 98, 98, 818, 818, 820, 1141, 1070, 370, 331, 133, - /* 710 */ 1066, 1141, 1250, 198, 268, 324, 1016, 330, 245, 333, - /* 720 */ 24, 334, 950, 951, 952, 368, 335, 81, 96, 96, - /* 730 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 99, - /* 740 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, - /* 750 */ 98, 98, 98, 98, 132, 267, 260, 445, 330, 223, - /* 760 */ 175, 1289, 925, 752, 724, 318, 1073, 324, 751, 246, - /* 770 */ 385, 301, 301, 378, 329, 361, 344, 414, 1233, 280, - /* 780 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 790 */ 350, 99, 88, 90, 971, 971, 847, 850, 839, 839, - /* 800 */ 97, 97, 98, 98, 98, 98, 337, 346, 721, 722, - /* 810 */ 449, 120, 118, 887, 162, 887, 810, 371, 324, 202, - /* 820 */ 202, 373, 249, 263, 202, 394, 74, 704, 208, 1069, - /* 830 */ 12, 12, 96, 96, 96, 96, 95, 95, 94, 94, - /* 840 */ 94, 93, 350, 100, 90, 971, 971, 847, 850, 839, - /* 850 */ 839, 97, 97, 98, 98, 98, 98, 449, 771, 232, - /* 860 */ 449, 278, 120, 286, 74, 704, 714, 713, 324, 342, - /* 870 */ 749, 877, 1209, 77, 285, 1255, 780, 52, 52, 202, - /* 880 */ 27, 27, 418, 96, 96, 96, 96, 95, 95, 94, - /* 890 */ 94, 94, 93, 350, 90, 971, 971, 847, 850, 839, - /* 900 */ 839, 97, 97, 98, 98, 98, 98, 86, 444, 877, - /* 910 */ 3, 1193, 422, 1013, 873, 435, 886, 208, 886, 689, - /* 920 */ 1091, 257, 116, 822, 447, 1230, 117, 1229, 86, 444, - /* 930 */ 177, 3, 381, 96, 96, 96, 96, 95, 95, 94, - /* 940 */ 94, 94, 93, 350, 339, 447, 120, 351, 120, 212, - /* 950 */ 169, 287, 404, 282, 403, 199, 771, 950, 433, 419, - /* 960 */ 439, 822, 280, 691, 1039, 264, 269, 132, 351, 153, - /* 970 */ 826, 376, 74, 272, 274, 276, 83, 84, 1054, 433, - /* 980 */ 147, 1038, 443, 85, 351, 451, 450, 281, 132, 818, - /* 990 */ 25, 826, 449, 120, 950, 951, 952, 83, 84, 86, - /* 1000 */ 444, 691, 3, 408, 85, 351, 451, 450, 449, 5, - /* 1010 */ 818, 203, 32, 32, 1107, 120, 447, 950, 225, 1140, - /* 1020 */ 818, 818, 820, 821, 19, 203, 226, 950, 38, 38, - /* 1030 */ 1087, 314, 314, 313, 215, 311, 120, 449, 678, 351, - /* 1040 */ 237, 818, 818, 820, 821, 19, 969, 409, 377, 1, - /* 1050 */ 433, 180, 706, 248, 950, 951, 952, 10, 10, 449, - /* 1060 */ 969, 247, 826, 1098, 950, 951, 952, 430, 83, 84, - /* 1070 */ 756, 336, 950, 20, 431, 85, 351, 451, 450, 10, - /* 1080 */ 10, 818, 86, 444, 969, 3, 950, 449, 302, 303, - /* 1090 */ 182, 950, 1146, 338, 1021, 1015, 1004, 183, 969, 447, - /* 1100 */ 132, 181, 76, 444, 21, 3, 449, 10, 10, 950, - /* 1110 */ 951, 952, 818, 818, 820, 821, 19, 715, 1279, 447, - /* 1120 */ 389, 233, 351, 950, 951, 952, 10, 10, 950, 951, - /* 1130 */ 952, 1003, 218, 433, 1005, 325, 1273, 773, 289, 291, - /* 1140 */ 424, 293, 351, 7, 159, 826, 363, 402, 315, 360, - /* 1150 */ 1129, 83, 84, 433, 1232, 716, 772, 259, 85, 351, - /* 1160 */ 451, 450, 358, 375, 818, 826, 360, 359, 399, 1211, - /* 1170 */ 157, 83, 84, 681, 98, 98, 98, 98, 85, 351, - /* 1180 */ 451, 450, 323, 252, 818, 295, 1211, 1213, 1235, 173, - /* 1190 */ 1037, 284, 434, 340, 1204, 818, 818, 820, 821, 19, - /* 1200 */ 308, 234, 449, 234, 96, 96, 96, 96, 95, 95, - /* 1210 */ 94, 94, 94, 93, 350, 818, 818, 820, 821, 19, - /* 1220 */ 909, 120, 39, 39, 1203, 449, 168, 360, 449, 1276, - /* 1230 */ 367, 449, 135, 449, 986, 910, 449, 1249, 449, 1247, - /* 1240 */ 449, 205, 983, 449, 370, 40, 40, 1211, 41, 41, - /* 1250 */ 911, 42, 42, 28, 28, 870, 29, 29, 31, 31, - /* 1260 */ 43, 43, 379, 44, 44, 449, 59, 449, 332, 449, - /* 1270 */ 432, 62, 144, 156, 449, 130, 449, 72, 449, 137, - /* 1280 */ 449, 365, 449, 392, 139, 45, 45, 11, 11, 46, - /* 1290 */ 46, 140, 1200, 449, 105, 105, 47, 47, 48, 48, - /* 1300 */ 33, 33, 49, 49, 1126, 449, 141, 366, 449, 185, - /* 1310 */ 142, 449, 1234, 50, 50, 449, 160, 449, 148, 449, - /* 1320 */ 1136, 382, 449, 67, 449, 34, 34, 449, 122, 122, - /* 1330 */ 449, 123, 123, 449, 1198, 124, 124, 56, 56, 35, - /* 1340 */ 35, 449, 106, 106, 53, 53, 449, 107, 107, 449, - /* 1350 */ 108, 108, 449, 104, 104, 449, 406, 449, 388, 449, - /* 1360 */ 189, 121, 121, 449, 190, 449, 119, 119, 449, 112, - /* 1370 */ 112, 449, 111, 111, 1218, 109, 109, 110, 110, 55, - /* 1380 */ 55, 266, 752, 57, 57, 54, 54, 751, 26, 26, - /* 1390 */ 1099, 30, 30, 219, 154, 390, 271, 191, 321, 1006, - /* 1400 */ 192, 405, 1057, 1056, 1055, 341, 1048, 706, 1047, 1029, - /* 1410 */ 322, 420, 1028, 71, 1095, 283, 288, 1027, 1288, 204, - /* 1420 */ 6, 297, 79, 1184, 437, 1096, 1094, 290, 345, 292, - /* 1430 */ 441, 1093, 294, 102, 425, 73, 423, 213, 1012, 22, - /* 1440 */ 452, 945, 214, 1077, 216, 217, 238, 453, 306, 304, - /* 1450 */ 307, 239, 240, 1001, 305, 125, 996, 126, 115, 235, - /* 1460 */ 127, 665, 352, 166, 244, 179, 356, 113, 885, 883, - /* 1470 */ 806, 136, 128, 738, 326, 138, 327, 258, 184, 899, - /* 1480 */ 143, 129, 145, 63, 64, 65, 66, 902, 186, 187, - /* 1490 */ 898, 8, 13, 188, 134, 265, 891, 202, 980, 387, - /* 1500 */ 150, 149, 680, 161, 391, 193, 285, 279, 395, 151, - /* 1510 */ 68, 717, 14, 15, 400, 69, 16, 131, 236, 825, - /* 1520 */ 824, 853, 746, 750, 4, 70, 174, 413, 220, 222, - /* 1530 */ 152, 779, 774, 77, 868, 74, 854, 201, 17, 852, - /* 1540 */ 908, 206, 907, 207, 18, 857, 934, 163, 436, 210, - /* 1550 */ 935, 164, 209, 165, 440, 856, 823, 312, 690, 87, - /* 1560 */ 211, 309, 1281, 940, 995, 1280, + /* 0 */ 349, 99, 96, 185, 99, 96, 185, 233, 1047, 1, + /* 10 */ 1, 489, 2, 1051, 484, 477, 477, 477, 260, 351, + /* 20 */ 121, 1310, 1120, 1120, 1178, 1115, 1094, 1128, 380, 380, + /* 30 */ 380, 835, 454, 410, 1115, 59, 59, 1357, 425, 836, + /* 40 */ 710, 711, 712, 106, 107, 97, 1023, 1023, 900, 903, + /* 50 */ 892, 892, 104, 104, 105, 105, 105, 105, 346, 238, + /* 60 */ 238, 99, 96, 185, 238, 238, 889, 889, 901, 904, + /* 70 */ 460, 481, 351, 99, 96, 185, 481, 347, 1177, 82, + /* 80 */ 388, 214, 182, 23, 194, 103, 103, 103, 103, 102, + /* 90 */ 102, 101, 101, 101, 100, 381, 106, 107, 97, 1023, + /* 100 */ 1023, 900, 903, 892, 892, 104, 104, 105, 105, 105, + /* 110 */ 105, 10, 385, 484, 24, 484, 1333, 489, 2, 1051, + /* 120 */ 335, 1043, 108, 893, 260, 351, 121, 99, 96, 185, + /* 130 */ 100, 381, 386, 1128, 59, 59, 59, 59, 103, 103, + /* 140 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 106, + /* 150 */ 107, 97, 1023, 1023, 900, 903, 892, 892, 104, 104, + /* 160 */ 105, 105, 105, 105, 360, 238, 238, 170, 170, 467, + /* 170 */ 455, 467, 464, 67, 381, 329, 169, 481, 351, 343, + /* 180 */ 338, 400, 1044, 68, 101, 101, 101, 100, 381, 393, + /* 190 */ 194, 103, 103, 103, 103, 102, 102, 101, 101, 101, + /* 200 */ 100, 381, 106, 107, 97, 1023, 1023, 900, 903, 892, + /* 210 */ 892, 104, 104, 105, 105, 105, 105, 483, 385, 103, + /* 220 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381, + /* 230 */ 268, 351, 946, 946, 422, 296, 102, 102, 101, 101, + /* 240 */ 101, 100, 381, 861, 103, 103, 103, 103, 102, 102, + /* 250 */ 101, 101, 101, 100, 381, 106, 107, 97, 1023, 1023, + /* 260 */ 900, 903, 892, 892, 104, 104, 105, 105, 105, 105, + /* 270 */ 484, 983, 1383, 206, 1353, 1383, 438, 435, 434, 281, + /* 280 */ 396, 269, 1089, 941, 351, 1002, 433, 861, 743, 401, + /* 290 */ 282, 57, 57, 482, 145, 791, 791, 103, 103, 103, + /* 300 */ 103, 102, 102, 101, 101, 101, 100, 381, 106, 107, + /* 310 */ 97, 1023, 1023, 900, 903, 892, 892, 104, 104, 105, + /* 320 */ 105, 105, 105, 281, 1002, 1003, 1004, 206, 879, 319, + /* 330 */ 438, 435, 434, 981, 259, 474, 360, 351, 1118, 1118, + /* 340 */ 433, 736, 379, 378, 872, 1002, 1356, 322, 871, 766, + /* 350 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100, + /* 360 */ 381, 106, 107, 97, 1023, 1023, 900, 903, 892, 892, + /* 370 */ 104, 104, 105, 105, 105, 105, 484, 801, 484, 871, + /* 380 */ 871, 873, 401, 282, 1002, 1003, 1004, 1030, 360, 1030, + /* 390 */ 351, 983, 1384, 213, 880, 1384, 145, 59, 59, 59, + /* 400 */ 59, 1002, 244, 103, 103, 103, 103, 102, 102, 101, + /* 410 */ 101, 101, 100, 381, 106, 107, 97, 1023, 1023, 900, + /* 420 */ 903, 892, 892, 104, 104, 105, 105, 105, 105, 274, + /* 430 */ 484, 110, 467, 479, 467, 444, 259, 474, 232, 232, + /* 440 */ 1002, 1003, 1004, 351, 210, 335, 982, 866, 1385, 336, + /* 450 */ 481, 59, 59, 981, 245, 307, 103, 103, 103, 103, + /* 460 */ 102, 102, 101, 101, 101, 100, 381, 106, 107, 97, + /* 470 */ 1023, 1023, 900, 903, 892, 892, 104, 104, 105, 105, + /* 480 */ 105, 105, 453, 459, 484, 408, 377, 259, 474, 271, + /* 490 */ 183, 273, 209, 208, 207, 356, 351, 307, 178, 177, + /* 500 */ 127, 1006, 1098, 14, 14, 43, 43, 1044, 425, 103, + /* 510 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381, + /* 520 */ 106, 107, 97, 1023, 1023, 900, 903, 892, 892, 104, + /* 530 */ 104, 105, 105, 105, 105, 294, 1132, 408, 160, 484, + /* 540 */ 408, 1006, 129, 962, 1209, 239, 239, 481, 307, 425, + /* 550 */ 1309, 1097, 351, 235, 243, 272, 820, 481, 963, 425, + /* 560 */ 11, 11, 103, 103, 103, 103, 102, 102, 101, 101, + /* 570 */ 101, 100, 381, 964, 362, 1002, 106, 107, 97, 1023, + /* 580 */ 1023, 900, 903, 892, 892, 104, 104, 105, 105, 105, + /* 590 */ 105, 1275, 161, 126, 777, 289, 1209, 292, 1072, 357, + /* 600 */ 1209, 1127, 476, 357, 778, 425, 247, 425, 351, 248, + /* 610 */ 414, 364, 414, 171, 1002, 1003, 1004, 84, 103, 103, + /* 620 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 1002, + /* 630 */ 184, 484, 106, 107, 97, 1023, 1023, 900, 903, 892, + /* 640 */ 892, 104, 104, 105, 105, 105, 105, 1123, 1209, 287, + /* 650 */ 484, 1209, 11, 11, 179, 820, 259, 474, 307, 237, + /* 660 */ 182, 351, 321, 365, 414, 308, 367, 366, 1002, 1003, + /* 670 */ 1004, 44, 44, 87, 103, 103, 103, 103, 102, 102, + /* 680 */ 101, 101, 101, 100, 381, 106, 107, 97, 1023, 1023, + /* 690 */ 900, 903, 892, 892, 104, 104, 105, 105, 105, 105, + /* 700 */ 246, 368, 280, 128, 10, 358, 146, 796, 835, 258, + /* 710 */ 1020, 88, 795, 86, 351, 421, 836, 943, 376, 348, + /* 720 */ 191, 943, 1318, 267, 308, 279, 456, 103, 103, 103, + /* 730 */ 103, 102, 102, 101, 101, 101, 100, 381, 106, 95, + /* 740 */ 97, 1023, 1023, 900, 903, 892, 892, 104, 104, 105, + /* 750 */ 105, 105, 105, 420, 249, 238, 238, 238, 238, 79, + /* 760 */ 375, 125, 305, 29, 262, 978, 351, 481, 337, 481, + /* 770 */ 756, 755, 304, 278, 415, 15, 81, 940, 1126, 940, + /* 780 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100, + /* 790 */ 381, 107, 97, 1023, 1023, 900, 903, 892, 892, 104, + /* 800 */ 104, 105, 105, 105, 105, 457, 263, 484, 174, 484, + /* 810 */ 238, 238, 863, 407, 402, 216, 216, 351, 409, 193, + /* 820 */ 283, 216, 481, 81, 763, 764, 266, 5, 13, 13, + /* 830 */ 34, 34, 103, 103, 103, 103, 102, 102, 101, 101, + /* 840 */ 101, 100, 381, 97, 1023, 1023, 900, 903, 892, 892, + /* 850 */ 104, 104, 105, 105, 105, 105, 93, 475, 1002, 4, + /* 860 */ 403, 1002, 340, 431, 1002, 297, 212, 1277, 81, 746, + /* 870 */ 1163, 152, 926, 478, 166, 212, 757, 829, 930, 939, + /* 880 */ 216, 939, 858, 103, 103, 103, 103, 102, 102, 101, + /* 890 */ 101, 101, 100, 381, 238, 238, 382, 1002, 1003, 1004, + /* 900 */ 1002, 1003, 1004, 1002, 1003, 1004, 481, 439, 472, 746, + /* 910 */ 105, 105, 105, 105, 98, 758, 1162, 145, 930, 412, + /* 920 */ 879, 406, 793, 81, 395, 89, 90, 91, 105, 105, + /* 930 */ 105, 105, 1323, 92, 484, 382, 486, 485, 240, 275, + /* 940 */ 871, 103, 103, 103, 103, 102, 102, 101, 101, 101, + /* 950 */ 100, 381, 1096, 371, 355, 45, 45, 259, 474, 103, + /* 960 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381, + /* 970 */ 1150, 871, 871, 873, 874, 21, 1332, 991, 384, 730, + /* 980 */ 722, 242, 123, 1298, 124, 875, 333, 333, 332, 227, + /* 990 */ 330, 991, 384, 719, 256, 242, 484, 391, 413, 1297, + /* 1000 */ 333, 333, 332, 227, 330, 748, 187, 719, 265, 470, + /* 1010 */ 1279, 1002, 484, 417, 391, 390, 264, 11, 11, 284, + /* 1020 */ 187, 732, 265, 93, 475, 875, 4, 1279, 1281, 419, + /* 1030 */ 264, 369, 416, 11, 11, 1159, 288, 484, 399, 1346, + /* 1040 */ 478, 379, 378, 291, 484, 293, 189, 250, 295, 1027, + /* 1050 */ 1002, 1003, 1004, 190, 1029, 1111, 140, 188, 11, 11, + /* 1060 */ 189, 732, 1028, 382, 923, 46, 46, 190, 1095, 230, + /* 1070 */ 140, 188, 462, 93, 475, 472, 4, 300, 309, 391, + /* 1080 */ 373, 6, 1069, 217, 739, 310, 1030, 879, 1030, 1171, + /* 1090 */ 478, 352, 1279, 90, 91, 800, 259, 474, 1208, 484, + /* 1100 */ 92, 1268, 382, 486, 485, 352, 1002, 871, 879, 426, + /* 1110 */ 259, 474, 172, 382, 238, 238, 1146, 170, 1021, 389, + /* 1120 */ 47, 47, 1157, 739, 872, 472, 481, 469, 871, 350, + /* 1130 */ 1214, 83, 475, 389, 4, 1078, 1071, 879, 871, 871, + /* 1140 */ 873, 874, 21, 90, 91, 1002, 1003, 1004, 478, 251, + /* 1150 */ 92, 251, 382, 486, 485, 443, 370, 871, 1021, 871, + /* 1160 */ 871, 873, 224, 241, 306, 441, 301, 440, 211, 1060, + /* 1170 */ 820, 382, 822, 447, 299, 1059, 484, 1061, 1143, 962, + /* 1180 */ 430, 796, 484, 472, 1340, 312, 795, 465, 871, 871, + /* 1190 */ 873, 874, 21, 314, 963, 879, 316, 59, 59, 1002, + /* 1200 */ 9, 90, 91, 48, 48, 238, 238, 210, 92, 964, + /* 1210 */ 382, 486, 485, 176, 334, 871, 242, 481, 1193, 238, + /* 1220 */ 238, 333, 333, 332, 227, 330, 394, 270, 719, 277, + /* 1230 */ 471, 481, 467, 466, 484, 145, 217, 1201, 1002, 1003, + /* 1240 */ 1004, 187, 3, 265, 184, 445, 871, 871, 873, 874, + /* 1250 */ 21, 264, 1337, 450, 1051, 39, 39, 392, 356, 260, + /* 1260 */ 342, 121, 468, 411, 436, 821, 180, 1094, 1128, 820, + /* 1270 */ 303, 1021, 1272, 1271, 299, 259, 474, 238, 238, 1002, + /* 1280 */ 473, 189, 484, 318, 327, 238, 238, 484, 190, 481, + /* 1290 */ 446, 140, 188, 1343, 238, 238, 1038, 481, 148, 175, + /* 1300 */ 238, 238, 484, 49, 49, 219, 481, 484, 35, 35, + /* 1310 */ 1317, 1021, 481, 484, 1035, 484, 1315, 484, 1002, 1003, + /* 1320 */ 1004, 484, 66, 36, 36, 194, 352, 484, 38, 38, + /* 1330 */ 484, 259, 474, 69, 50, 50, 51, 51, 52, 52, + /* 1340 */ 359, 484, 12, 12, 484, 1198, 484, 158, 53, 53, + /* 1350 */ 405, 112, 112, 385, 389, 484, 26, 484, 143, 484, + /* 1360 */ 150, 484, 54, 54, 397, 40, 40, 55, 55, 484, + /* 1370 */ 79, 484, 153, 1190, 484, 154, 56, 56, 41, 41, + /* 1380 */ 58, 58, 133, 133, 484, 398, 484, 429, 484, 155, + /* 1390 */ 134, 134, 135, 135, 484, 63, 63, 484, 341, 484, + /* 1400 */ 339, 484, 196, 484, 156, 42, 42, 113, 113, 60, + /* 1410 */ 60, 484, 404, 484, 27, 114, 114, 1204, 115, 115, + /* 1420 */ 111, 111, 132, 132, 131, 131, 1266, 418, 484, 162, + /* 1430 */ 484, 200, 119, 119, 118, 118, 484, 74, 424, 484, + /* 1440 */ 1286, 484, 231, 484, 202, 484, 167, 286, 427, 116, + /* 1450 */ 116, 117, 117, 290, 203, 442, 1062, 62, 62, 204, + /* 1460 */ 64, 64, 61, 61, 33, 33, 37, 37, 344, 372, + /* 1470 */ 1114, 1105, 748, 1113, 374, 1112, 254, 458, 1086, 255, + /* 1480 */ 345, 1085, 302, 1084, 1355, 78, 1154, 311, 1104, 449, + /* 1490 */ 452, 1155, 1153, 218, 7, 313, 315, 320, 1152, 85, + /* 1500 */ 1252, 317, 109, 80, 463, 225, 461, 1068, 25, 487, + /* 1510 */ 997, 323, 257, 226, 229, 228, 1136, 324, 325, 326, + /* 1520 */ 488, 136, 1057, 1052, 1302, 1303, 1301, 706, 1300, 137, + /* 1530 */ 122, 138, 383, 173, 1082, 261, 186, 252, 1081, 65, + /* 1540 */ 387, 120, 938, 936, 855, 353, 149, 1079, 139, 151, + /* 1550 */ 192, 780, 195, 276, 952, 157, 141, 361, 70, 363, + /* 1560 */ 859, 159, 71, 72, 142, 73, 955, 354, 147, 197, + /* 1570 */ 198, 951, 130, 16, 199, 285, 216, 1032, 201, 423, + /* 1580 */ 164, 944, 163, 28, 721, 428, 304, 165, 205, 759, + /* 1590 */ 75, 432, 298, 17, 18, 437, 76, 253, 878, 144, + /* 1600 */ 877, 906, 77, 986, 30, 448, 987, 31, 451, 181, + /* 1610 */ 234, 236, 168, 828, 823, 89, 910, 921, 81, 907, + /* 1620 */ 215, 905, 909, 961, 960, 19, 221, 20, 220, 22, + /* 1630 */ 32, 331, 876, 731, 94, 790, 794, 8, 992, 222, + /* 1640 */ 480, 328, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, + /* 1650 */ 223, 1048, 1048, 1048, 1048, 1348, 1347, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 144, 145, 146, 147, 24, 90, 91, 92, 93, - /* 10 */ 94, 54, 55, 56, 57, 58, 88, 89, 90, 91, - /* 20 */ 92, 93, 94, 152, 43, 44, 45, 46, 47, 48, - /* 30 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 94, - /* 40 */ 59, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 50 */ 93, 94, 59, 84, 85, 86, 87, 88, 89, 90, - /* 60 */ 91, 92, 93, 94, 193, 84, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 93, 94, 194, 195, 97, 79, - /* 80 */ 11, 88, 89, 152, 26, 19, 171, 152, 206, 96, - /* 90 */ 97, 98, 72, 100, 179, 59, 152, 31, 163, 79, - /* 100 */ 107, 219, 109, 172, 173, 39, 79, 172, 173, 43, - /* 110 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 120 */ 54, 55, 56, 57, 152, 132, 199, 134, 108, 109, - /* 130 */ 110, 196, 96, 97, 98, 99, 209, 19, 102, 103, - /* 140 */ 104, 72, 207, 208, 26, 72, 119, 120, 79, 113, - /* 150 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 160 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 170 */ 52, 53, 54, 55, 56, 57, 31, 108, 109, 110, - /* 180 */ 82, 108, 109, 110, 39, 210, 68, 175, 130, 19, - /* 190 */ 218, 175, 119, 120, 250, 97, 221, 222, 223, 101, - /* 200 */ 172, 152, 84, 85, 86, 87, 88, 89, 90, 91, - /* 210 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, - /* 220 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 152, - /* 230 */ 132, 133, 134, 221, 222, 223, 66, 221, 222, 223, - /* 240 */ 172, 19, 193, 22, 23, 152, 24, 26, 172, 173, - /* 250 */ 46, 47, 48, 49, 84, 85, 86, 87, 88, 89, - /* 260 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, - /* 270 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 280 */ 221, 222, 223, 207, 208, 46, 22, 23, 148, 149, - /* 290 */ 26, 242, 172, 19, 154, 218, 156, 23, 88, 89, - /* 300 */ 241, 59, 163, 163, 83, 101, 84, 85, 86, 87, - /* 310 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, - /* 320 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 330 */ 56, 57, 152, 157, 152, 196, 196, 16, 96, 97, - /* 340 */ 98, 26, 132, 250, 134, 19, 107, 83, 59, 23, - /* 350 */ 211, 212, 172, 173, 172, 173, 1, 2, 84, 85, - /* 360 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, - /* 370 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 380 */ 54, 55, 56, 57, 244, 152, 97, 207, 208, 207, - /* 390 */ 208, 185, 221, 222, 223, 152, 75, 19, 77, 179, - /* 400 */ 180, 23, 93, 94, 228, 172, 173, 231, 188, 152, - /* 410 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 420 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 430 */ 52, 53, 54, 55, 56, 57, 193, 152, 123, 152, - /* 440 */ 207, 208, 152, 168, 169, 170, 168, 169, 170, 19, - /* 450 */ 160, 22, 23, 23, 164, 119, 120, 172, 173, 172, - /* 460 */ 173, 140, 84, 85, 86, 87, 88, 89, 90, 91, - /* 470 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, - /* 480 */ 50, 51, 52, 53, 54, 55, 56, 57, 99, 22, - /* 490 */ 23, 102, 103, 104, 194, 195, 0, 1, 2, 247, - /* 500 */ 248, 19, 113, 190, 191, 23, 206, 190, 191, 59, - /* 510 */ 225, 152, 83, 152, 84, 85, 86, 87, 88, 89, - /* 520 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, - /* 530 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 540 */ 90, 181, 152, 108, 109, 110, 96, 97, 98, 115, - /* 550 */ 83, 117, 118, 19, 193, 152, 23, 152, 152, 26, - /* 560 */ 29, 152, 172, 173, 33, 152, 84, 85, 86, 87, - /* 570 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, - /* 580 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 590 */ 56, 57, 22, 152, 16, 64, 193, 207, 152, 193, - /* 600 */ 12, 7, 8, 9, 152, 108, 109, 110, 19, 152, - /* 610 */ 164, 146, 147, 172, 173, 27, 163, 181, 84, 85, - /* 620 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 59, - /* 630 */ 42, 98, 43, 44, 45, 46, 47, 48, 49, 50, - /* 640 */ 51, 52, 53, 54, 55, 56, 57, 238, 22, 196, - /* 650 */ 62, 163, 82, 75, 152, 77, 152, 124, 88, 89, - /* 660 */ 72, 152, 137, 19, 139, 152, 96, 97, 24, 152, - /* 670 */ 152, 101, 138, 84, 85, 86, 87, 88, 89, 90, - /* 680 */ 91, 92, 93, 94, 196, 59, 19, 43, 44, 45, - /* 690 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 700 */ 56, 57, 132, 133, 134, 152, 193, 219, 245, 246, - /* 710 */ 193, 152, 152, 46, 152, 19, 166, 167, 152, 217, - /* 720 */ 232, 217, 96, 97, 98, 237, 217, 138, 84, 85, - /* 730 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, - /* 740 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 750 */ 54, 55, 56, 57, 79, 193, 238, 166, 167, 211, - /* 760 */ 212, 23, 23, 116, 26, 26, 195, 19, 121, 152, - /* 770 */ 217, 152, 152, 152, 107, 100, 217, 206, 163, 112, - /* 780 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 790 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 800 */ 52, 53, 54, 55, 56, 57, 187, 187, 7, 8, - /* 810 */ 152, 196, 22, 132, 24, 134, 23, 23, 19, 26, - /* 820 */ 26, 23, 152, 23, 26, 23, 26, 59, 26, 163, - /* 830 */ 172, 173, 84, 85, 86, 87, 88, 89, 90, 91, - /* 840 */ 92, 93, 94, 44, 45, 46, 47, 48, 49, 50, - /* 850 */ 51, 52, 53, 54, 55, 56, 57, 152, 26, 238, - /* 860 */ 152, 23, 196, 101, 26, 97, 100, 101, 19, 19, - /* 870 */ 23, 59, 152, 26, 112, 152, 23, 172, 173, 26, - /* 880 */ 172, 173, 19, 84, 85, 86, 87, 88, 89, 90, - /* 890 */ 91, 92, 93, 94, 45, 46, 47, 48, 49, 50, - /* 900 */ 51, 52, 53, 54, 55, 56, 57, 19, 20, 97, - /* 910 */ 22, 23, 207, 163, 23, 163, 132, 26, 134, 23, - /* 920 */ 213, 152, 26, 59, 36, 152, 22, 152, 19, 20, - /* 930 */ 98, 22, 152, 84, 85, 86, 87, 88, 89, 90, - /* 940 */ 91, 92, 93, 94, 94, 36, 196, 59, 196, 99, - /* 950 */ 100, 101, 102, 103, 104, 105, 124, 59, 70, 96, - /* 960 */ 163, 97, 112, 59, 181, 152, 152, 79, 59, 71, - /* 970 */ 82, 19, 26, 152, 152, 152, 88, 89, 152, 70, - /* 980 */ 22, 152, 163, 95, 96, 97, 98, 152, 79, 101, - /* 990 */ 22, 82, 152, 196, 96, 97, 98, 88, 89, 19, - /* 1000 */ 20, 97, 22, 163, 95, 96, 97, 98, 152, 22, - /* 1010 */ 101, 24, 172, 173, 152, 196, 36, 59, 22, 152, - /* 1020 */ 132, 133, 134, 135, 136, 24, 5, 59, 172, 173, - /* 1030 */ 152, 10, 11, 12, 13, 14, 196, 152, 17, 59, - /* 1040 */ 210, 132, 133, 134, 135, 136, 59, 207, 96, 22, - /* 1050 */ 70, 30, 106, 32, 96, 97, 98, 172, 173, 152, - /* 1060 */ 59, 40, 82, 152, 96, 97, 98, 152, 88, 89, - /* 1070 */ 90, 186, 59, 22, 191, 95, 96, 97, 98, 172, - /* 1080 */ 173, 101, 19, 20, 97, 22, 59, 152, 152, 152, - /* 1090 */ 69, 59, 152, 186, 152, 152, 152, 76, 97, 36, - /* 1100 */ 79, 80, 19, 20, 53, 22, 152, 172, 173, 96, - /* 1110 */ 97, 98, 132, 133, 134, 135, 136, 35, 122, 36, - /* 1120 */ 234, 186, 59, 96, 97, 98, 172, 173, 96, 97, - /* 1130 */ 98, 152, 233, 70, 152, 114, 152, 124, 210, 210, - /* 1140 */ 186, 210, 59, 198, 197, 82, 214, 65, 150, 152, - /* 1150 */ 201, 88, 89, 70, 201, 73, 124, 239, 95, 96, - /* 1160 */ 97, 98, 141, 239, 101, 82, 169, 170, 176, 152, - /* 1170 */ 152, 88, 89, 21, 54, 55, 56, 57, 95, 96, - /* 1180 */ 97, 98, 164, 214, 101, 214, 169, 170, 163, 184, - /* 1190 */ 180, 175, 227, 111, 175, 132, 133, 134, 135, 136, - /* 1200 */ 200, 183, 152, 185, 84, 85, 86, 87, 88, 89, - /* 1210 */ 90, 91, 92, 93, 94, 132, 133, 134, 135, 136, - /* 1220 */ 12, 196, 172, 173, 175, 152, 198, 230, 152, 155, - /* 1230 */ 78, 152, 243, 152, 60, 27, 152, 159, 152, 159, - /* 1240 */ 152, 122, 38, 152, 219, 172, 173, 230, 172, 173, - /* 1250 */ 42, 172, 173, 172, 173, 103, 172, 173, 172, 173, - /* 1260 */ 172, 173, 237, 172, 173, 152, 240, 152, 159, 152, - /* 1270 */ 62, 240, 22, 220, 152, 43, 152, 130, 152, 189, - /* 1280 */ 152, 18, 152, 18, 192, 172, 173, 172, 173, 172, - /* 1290 */ 173, 192, 140, 152, 172, 173, 172, 173, 172, 173, - /* 1300 */ 172, 173, 172, 173, 201, 152, 192, 159, 152, 158, - /* 1310 */ 192, 152, 201, 172, 173, 152, 220, 152, 189, 152, - /* 1320 */ 189, 159, 152, 137, 152, 172, 173, 152, 172, 173, - /* 1330 */ 152, 172, 173, 152, 201, 172, 173, 172, 173, 172, - /* 1340 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152, - /* 1350 */ 172, 173, 152, 172, 173, 152, 90, 152, 61, 152, - /* 1360 */ 158, 172, 173, 152, 158, 152, 172, 173, 152, 172, - /* 1370 */ 173, 152, 172, 173, 236, 172, 173, 172, 173, 172, - /* 1380 */ 173, 235, 116, 172, 173, 172, 173, 121, 172, 173, - /* 1390 */ 159, 172, 173, 159, 22, 177, 159, 158, 177, 159, - /* 1400 */ 158, 107, 174, 174, 174, 63, 182, 106, 182, 174, - /* 1410 */ 177, 125, 176, 107, 216, 174, 215, 174, 174, 159, - /* 1420 */ 22, 159, 137, 224, 177, 216, 216, 215, 94, 215, - /* 1430 */ 177, 216, 215, 129, 126, 128, 127, 25, 162, 26, - /* 1440 */ 161, 13, 153, 205, 153, 6, 226, 151, 202, 204, - /* 1450 */ 201, 229, 229, 151, 203, 165, 151, 165, 178, 178, - /* 1460 */ 165, 4, 3, 22, 142, 15, 81, 16, 23, 23, - /* 1470 */ 120, 131, 111, 20, 249, 123, 249, 16, 125, 1, - /* 1480 */ 123, 111, 131, 53, 53, 53, 53, 96, 34, 122, - /* 1490 */ 1, 5, 22, 107, 246, 140, 67, 26, 74, 41, - /* 1500 */ 107, 67, 20, 24, 19, 105, 112, 23, 66, 22, - /* 1510 */ 22, 28, 22, 22, 66, 22, 22, 37, 66, 23, - /* 1520 */ 23, 23, 116, 23, 22, 26, 122, 26, 23, 23, - /* 1530 */ 22, 96, 124, 26, 23, 26, 23, 34, 34, 23, - /* 1540 */ 23, 26, 23, 22, 34, 11, 23, 22, 24, 122, - /* 1550 */ 23, 22, 26, 22, 24, 23, 23, 15, 23, 22, - /* 1560 */ 122, 23, 122, 1, 251, 122, + /* 0 */ 174, 226, 227, 228, 226, 227, 228, 172, 145, 146, + /* 10 */ 147, 148, 149, 150, 153, 169, 170, 171, 155, 19, + /* 20 */ 157, 246, 192, 193, 177, 181, 182, 164, 169, 170, + /* 30 */ 171, 31, 164, 153, 190, 174, 175, 187, 153, 39, + /* 40 */ 7, 8, 9, 43, 44, 45, 46, 47, 48, 49, + /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 174, 196, + /* 60 */ 197, 226, 227, 228, 196, 197, 46, 47, 48, 49, + /* 70 */ 209, 208, 19, 226, 227, 228, 208, 174, 177, 26, + /* 80 */ 195, 213, 214, 22, 221, 85, 86, 87, 88, 89, + /* 90 */ 90, 91, 92, 93, 94, 95, 43, 44, 45, 46, + /* 100 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 110 */ 57, 172, 249, 153, 53, 153, 147, 148, 149, 150, + /* 120 */ 22, 23, 69, 103, 155, 19, 157, 226, 227, 228, + /* 130 */ 94, 95, 247, 164, 174, 175, 174, 175, 85, 86, + /* 140 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 43, + /* 150 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 160 */ 54, 55, 56, 57, 153, 196, 197, 153, 153, 209, + /* 170 */ 210, 209, 210, 67, 95, 161, 237, 208, 19, 165, + /* 180 */ 165, 242, 84, 24, 91, 92, 93, 94, 95, 223, + /* 190 */ 221, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 200 */ 94, 95, 43, 44, 45, 46, 47, 48, 49, 50, + /* 210 */ 51, 52, 53, 54, 55, 56, 57, 153, 249, 85, + /* 220 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 230 */ 219, 19, 109, 110, 111, 23, 89, 90, 91, 92, + /* 240 */ 93, 94, 95, 73, 85, 86, 87, 88, 89, 90, + /* 250 */ 91, 92, 93, 94, 95, 43, 44, 45, 46, 47, + /* 260 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 270 */ 153, 22, 23, 101, 173, 26, 104, 105, 106, 109, + /* 280 */ 110, 111, 181, 11, 19, 59, 114, 73, 23, 110, + /* 290 */ 111, 174, 175, 116, 80, 118, 119, 85, 86, 87, + /* 300 */ 88, 89, 90, 91, 92, 93, 94, 95, 43, 44, + /* 310 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + /* 320 */ 55, 56, 57, 109, 98, 99, 100, 101, 83, 153, + /* 330 */ 104, 105, 106, 84, 120, 121, 153, 19, 192, 193, + /* 340 */ 114, 23, 89, 90, 99, 59, 23, 230, 103, 26, + /* 350 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 360 */ 95, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 370 */ 52, 53, 54, 55, 56, 57, 153, 91, 153, 134, + /* 380 */ 135, 136, 110, 111, 98, 99, 100, 134, 153, 136, + /* 390 */ 19, 22, 23, 26, 23, 26, 80, 174, 175, 174, + /* 400 */ 175, 59, 219, 85, 86, 87, 88, 89, 90, 91, + /* 410 */ 92, 93, 94, 95, 43, 44, 45, 46, 47, 48, + /* 420 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 16, + /* 430 */ 153, 22, 209, 210, 209, 210, 120, 121, 196, 197, + /* 440 */ 98, 99, 100, 19, 46, 22, 23, 23, 252, 253, + /* 450 */ 208, 174, 175, 84, 219, 153, 85, 86, 87, 88, + /* 460 */ 89, 90, 91, 92, 93, 94, 95, 43, 44, 45, + /* 470 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 480 */ 56, 57, 153, 153, 153, 153, 209, 120, 121, 76, + /* 490 */ 153, 78, 109, 110, 111, 97, 19, 153, 89, 90, + /* 500 */ 198, 59, 183, 174, 175, 174, 175, 84, 153, 85, + /* 510 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 520 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 530 */ 53, 54, 55, 56, 57, 16, 197, 153, 22, 153, + /* 540 */ 153, 99, 198, 12, 153, 196, 197, 208, 153, 153, + /* 550 */ 195, 183, 19, 23, 222, 142, 26, 208, 27, 153, + /* 560 */ 174, 175, 85, 86, 87, 88, 89, 90, 91, 92, + /* 570 */ 93, 94, 95, 42, 188, 59, 43, 44, 45, 46, + /* 580 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 590 */ 57, 195, 22, 198, 63, 76, 153, 78, 167, 168, + /* 600 */ 153, 195, 167, 168, 73, 153, 222, 153, 19, 222, + /* 610 */ 153, 220, 153, 24, 98, 99, 100, 140, 85, 86, + /* 620 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 59, + /* 630 */ 100, 153, 43, 44, 45, 46, 47, 48, 49, 50, + /* 640 */ 51, 52, 53, 54, 55, 56, 57, 195, 153, 195, + /* 650 */ 153, 153, 174, 175, 26, 125, 120, 121, 153, 213, + /* 660 */ 214, 19, 153, 220, 153, 153, 188, 220, 98, 99, + /* 670 */ 100, 174, 175, 140, 85, 86, 87, 88, 89, 90, + /* 680 */ 91, 92, 93, 94, 95, 43, 44, 45, 46, 47, + /* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 700 */ 243, 189, 243, 198, 172, 250, 251, 117, 31, 201, + /* 710 */ 26, 139, 122, 141, 19, 220, 39, 29, 220, 211, + /* 720 */ 24, 33, 153, 164, 153, 164, 19, 85, 86, 87, + /* 730 */ 88, 89, 90, 91, 92, 93, 94, 95, 43, 44, + /* 740 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + /* 750 */ 55, 56, 57, 65, 243, 196, 197, 196, 197, 131, + /* 760 */ 189, 22, 103, 24, 153, 23, 19, 208, 26, 208, + /* 770 */ 102, 103, 113, 23, 242, 22, 26, 134, 164, 136, + /* 780 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 790 */ 95, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 800 */ 53, 54, 55, 56, 57, 98, 153, 153, 124, 153, + /* 810 */ 196, 197, 23, 23, 61, 26, 26, 19, 23, 123, + /* 820 */ 23, 26, 208, 26, 7, 8, 153, 22, 174, 175, + /* 830 */ 174, 175, 85, 86, 87, 88, 89, 90, 91, 92, + /* 840 */ 93, 94, 95, 45, 46, 47, 48, 49, 50, 51, + /* 850 */ 52, 53, 54, 55, 56, 57, 19, 20, 59, 22, + /* 860 */ 111, 59, 164, 23, 59, 23, 26, 153, 26, 59, + /* 870 */ 153, 72, 23, 36, 72, 26, 35, 23, 59, 134, + /* 880 */ 26, 136, 133, 85, 86, 87, 88, 89, 90, 91, + /* 890 */ 92, 93, 94, 95, 196, 197, 59, 98, 99, 100, + /* 900 */ 98, 99, 100, 98, 99, 100, 208, 66, 71, 99, + /* 910 */ 54, 55, 56, 57, 58, 74, 153, 80, 99, 19, + /* 920 */ 83, 223, 23, 26, 153, 26, 89, 90, 54, 55, + /* 930 */ 56, 57, 153, 96, 153, 98, 99, 100, 22, 153, + /* 940 */ 103, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 950 */ 94, 95, 183, 112, 158, 174, 175, 120, 121, 85, + /* 960 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 970 */ 215, 134, 135, 136, 137, 138, 0, 1, 2, 23, + /* 980 */ 21, 5, 26, 153, 22, 59, 10, 11, 12, 13, + /* 990 */ 14, 1, 2, 17, 212, 5, 153, 153, 98, 153, + /* 1000 */ 10, 11, 12, 13, 14, 108, 30, 17, 32, 193, + /* 1010 */ 153, 59, 153, 153, 170, 171, 40, 174, 175, 153, + /* 1020 */ 30, 59, 32, 19, 20, 99, 22, 170, 171, 233, + /* 1030 */ 40, 188, 236, 174, 175, 153, 153, 153, 79, 123, + /* 1040 */ 36, 89, 90, 153, 153, 153, 70, 188, 153, 97, + /* 1050 */ 98, 99, 100, 77, 102, 153, 80, 81, 174, 175, + /* 1060 */ 70, 99, 110, 59, 105, 174, 175, 77, 153, 238, + /* 1070 */ 80, 81, 188, 19, 20, 71, 22, 153, 153, 235, + /* 1080 */ 19, 22, 164, 24, 59, 153, 134, 83, 136, 153, + /* 1090 */ 36, 115, 235, 89, 90, 91, 120, 121, 153, 153, + /* 1100 */ 96, 142, 98, 99, 100, 115, 59, 103, 83, 239, + /* 1110 */ 120, 121, 199, 59, 196, 197, 153, 153, 59, 143, + /* 1120 */ 174, 175, 153, 98, 99, 71, 208, 153, 103, 165, + /* 1130 */ 153, 19, 20, 143, 22, 153, 153, 83, 134, 135, + /* 1140 */ 136, 137, 138, 89, 90, 98, 99, 100, 36, 185, + /* 1150 */ 96, 187, 98, 99, 100, 91, 95, 103, 99, 134, + /* 1160 */ 135, 136, 101, 102, 103, 104, 105, 106, 107, 153, + /* 1170 */ 26, 59, 125, 164, 113, 153, 153, 153, 212, 12, + /* 1180 */ 19, 117, 153, 71, 153, 212, 122, 164, 134, 135, + /* 1190 */ 136, 137, 138, 212, 27, 83, 212, 174, 175, 59, + /* 1200 */ 200, 89, 90, 174, 175, 196, 197, 46, 96, 42, + /* 1210 */ 98, 99, 100, 172, 151, 103, 5, 208, 203, 196, + /* 1220 */ 197, 10, 11, 12, 13, 14, 216, 216, 17, 244, + /* 1230 */ 63, 208, 209, 210, 153, 80, 24, 203, 98, 99, + /* 1240 */ 100, 30, 22, 32, 100, 164, 134, 135, 136, 137, + /* 1250 */ 138, 40, 148, 164, 150, 174, 175, 102, 97, 155, + /* 1260 */ 203, 157, 164, 244, 178, 125, 186, 182, 164, 125, + /* 1270 */ 177, 59, 177, 177, 113, 120, 121, 196, 197, 59, + /* 1280 */ 232, 70, 153, 216, 202, 196, 197, 153, 77, 208, + /* 1290 */ 209, 80, 81, 156, 196, 197, 60, 208, 248, 200, + /* 1300 */ 196, 197, 153, 174, 175, 123, 208, 153, 174, 175, + /* 1310 */ 160, 99, 208, 153, 38, 153, 160, 153, 98, 99, + /* 1320 */ 100, 153, 245, 174, 175, 221, 115, 153, 174, 175, + /* 1330 */ 153, 120, 121, 245, 174, 175, 174, 175, 174, 175, + /* 1340 */ 160, 153, 174, 175, 153, 225, 153, 22, 174, 175, + /* 1350 */ 97, 174, 175, 249, 143, 153, 224, 153, 43, 153, + /* 1360 */ 191, 153, 174, 175, 18, 174, 175, 174, 175, 153, + /* 1370 */ 131, 153, 194, 203, 153, 194, 174, 175, 174, 175, + /* 1380 */ 174, 175, 174, 175, 153, 160, 153, 18, 153, 194, + /* 1390 */ 174, 175, 174, 175, 153, 174, 175, 153, 225, 153, + /* 1400 */ 203, 153, 159, 153, 194, 174, 175, 174, 175, 174, + /* 1410 */ 175, 153, 203, 153, 224, 174, 175, 191, 174, 175, + /* 1420 */ 174, 175, 174, 175, 174, 175, 203, 160, 153, 191, + /* 1430 */ 153, 159, 174, 175, 174, 175, 153, 139, 62, 153, + /* 1440 */ 241, 153, 160, 153, 159, 153, 22, 240, 179, 174, + /* 1450 */ 175, 174, 175, 160, 159, 97, 160, 174, 175, 159, + /* 1460 */ 174, 175, 174, 175, 174, 175, 174, 175, 179, 64, + /* 1470 */ 176, 184, 108, 176, 95, 176, 234, 126, 176, 234, + /* 1480 */ 179, 178, 176, 176, 176, 97, 218, 217, 184, 179, + /* 1490 */ 179, 218, 218, 160, 22, 217, 217, 160, 218, 139, + /* 1500 */ 229, 217, 130, 129, 127, 25, 128, 163, 26, 162, + /* 1510 */ 13, 206, 231, 154, 6, 154, 207, 205, 204, 203, + /* 1520 */ 152, 166, 152, 152, 172, 172, 172, 4, 172, 166, + /* 1530 */ 180, 166, 3, 22, 172, 144, 15, 180, 172, 172, + /* 1540 */ 82, 16, 23, 23, 121, 254, 132, 172, 112, 124, + /* 1550 */ 24, 20, 126, 16, 1, 124, 112, 61, 53, 37, + /* 1560 */ 133, 132, 53, 53, 112, 53, 98, 254, 251, 34, + /* 1570 */ 123, 1, 5, 22, 97, 142, 26, 75, 123, 41, + /* 1580 */ 97, 68, 68, 24, 20, 19, 113, 22, 107, 28, + /* 1590 */ 22, 67, 23, 22, 22, 67, 22, 67, 23, 37, + /* 1600 */ 23, 23, 26, 23, 22, 24, 23, 22, 24, 123, + /* 1610 */ 23, 23, 22, 98, 125, 26, 11, 23, 26, 23, + /* 1620 */ 34, 23, 23, 23, 23, 34, 22, 34, 26, 22, + /* 1630 */ 22, 15, 23, 23, 22, 117, 23, 22, 1, 123, + /* 1640 */ 26, 23, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1650 */ 123, 255, 255, 255, 255, 123, 123, 255, 255, 255, + /* 1660 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1670 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1680 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1690 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1700 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1710 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1720 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1730 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1740 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1750 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1760 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1770 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1780 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1790 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* 1800 */ 255, 255, }; -#define YY_SHIFT_USE_DFLT (1566) -#define YY_SHIFT_COUNT (454) -#define YY_SHIFT_MIN (-84) -#define YY_SHIFT_MAX (1562) -static const short yy_shift_ofst[] = { - /* 0 */ 355, 888, 1021, 909, 1063, 1063, 1063, 1063, 20, -19, - /* 10 */ 66, 66, 170, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - /* 20 */ -7, -7, 36, 73, 69, 27, 118, 222, 274, 326, - /* 30 */ 378, 430, 482, 534, 589, 644, 696, 696, 696, 696, - /* 40 */ 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, - /* 50 */ 696, 696, 696, 748, 696, 799, 849, 849, 980, 1063, - /* 60 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - /* 70 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - /* 80 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - /* 90 */ 1083, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - /* 100 */ 1063, 1063, 1063, 1063, -43, 1120, 1120, 1120, 1120, 1120, - /* 110 */ -31, -72, -84, 242, 1152, 667, 210, 210, 242, 309, - /* 120 */ 336, -55, 1566, 1566, 1566, 850, 850, 850, 626, 626, - /* 130 */ 588, 588, 898, 221, 264, 242, 242, 242, 242, 242, - /* 140 */ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - /* 150 */ 242, 242, 242, 242, 242, 496, 675, 289, 289, 336, - /* 160 */ 0, 0, 0, 0, 0, 0, 1566, 1566, 1566, 570, - /* 170 */ 98, 98, 958, 389, 450, 968, 1013, 1032, 1027, 242, - /* 180 */ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - /* 190 */ 242, 242, 242, 242, 242, 1082, 1082, 1082, 242, 242, - /* 200 */ 533, 242, 242, 242, 987, 242, 242, 1208, 242, 242, - /* 210 */ 242, 242, 242, 242, 242, 242, 242, 242, 435, 531, - /* 220 */ 1001, 1001, 1001, 832, 434, 1266, 594, 58, 863, 863, - /* 230 */ 952, 58, 952, 946, 738, 239, 145, 863, 525, 145, - /* 240 */ 145, 315, 647, 790, 1174, 1119, 1119, 1204, 1204, 1119, - /* 250 */ 1250, 1232, 1147, 1263, 1263, 1263, 1263, 1119, 1265, 1147, - /* 260 */ 1250, 1232, 1232, 1147, 1119, 1265, 1186, 1297, 1119, 1119, - /* 270 */ 1265, 1372, 1119, 1265, 1119, 1265, 1372, 1294, 1294, 1294, - /* 280 */ 1342, 1372, 1294, 1301, 1294, 1342, 1294, 1294, 1286, 1306, - /* 290 */ 1286, 1306, 1286, 1306, 1286, 1306, 1119, 1398, 1119, 1285, - /* 300 */ 1372, 1334, 1334, 1372, 1304, 1308, 1307, 1309, 1147, 1412, - /* 310 */ 1413, 1428, 1428, 1439, 1439, 1439, 1566, 1566, 1566, 1566, - /* 320 */ 1566, 1566, 1566, 1566, 204, 321, 429, 467, 578, 497, - /* 330 */ 904, 739, 1051, 793, 794, 798, 800, 802, 838, 768, - /* 340 */ 766, 801, 762, 847, 853, 812, 891, 681, 784, 896, - /* 350 */ 864, 996, 1457, 1459, 1441, 1322, 1450, 1385, 1451, 1445, - /* 360 */ 1446, 1350, 1340, 1361, 1352, 1453, 1353, 1461, 1478, 1357, - /* 370 */ 1351, 1430, 1431, 1432, 1433, 1370, 1391, 1454, 1367, 1489, - /* 380 */ 1486, 1470, 1386, 1355, 1429, 1471, 1434, 1424, 1458, 1393, - /* 390 */ 1479, 1482, 1485, 1394, 1400, 1487, 1442, 1488, 1490, 1484, - /* 400 */ 1491, 1448, 1483, 1493, 1452, 1480, 1496, 1497, 1498, 1499, - /* 410 */ 1406, 1494, 1500, 1502, 1501, 1404, 1505, 1506, 1435, 1503, - /* 420 */ 1508, 1408, 1507, 1504, 1509, 1510, 1511, 1507, 1513, 1516, - /* 430 */ 1517, 1515, 1519, 1521, 1534, 1523, 1525, 1524, 1526, 1527, - /* 440 */ 1529, 1530, 1526, 1532, 1531, 1533, 1535, 1537, 1427, 1438, - /* 450 */ 1440, 1443, 1538, 1542, 1562, +#define YY_SHIFT_COUNT (489) +#define YY_SHIFT_MIN (0) +#define YY_SHIFT_MAX (1637) +static const unsigned short int yy_shift_ofst[] = { + /* 0 */ 990, 976, 1211, 837, 837, 316, 1054, 1054, 1054, 1054, + /* 10 */ 214, 0, 0, 106, 642, 1054, 1054, 1054, 1054, 1054, + /* 20 */ 1054, 1054, 1054, 952, 952, 226, 1155, 316, 316, 316, + /* 30 */ 316, 316, 316, 53, 159, 212, 265, 318, 371, 424, + /* 40 */ 477, 533, 589, 642, 642, 642, 642, 642, 642, 642, + /* 50 */ 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, + /* 60 */ 695, 642, 747, 798, 798, 1004, 1054, 1054, 1054, 1054, + /* 70 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + /* 80 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + /* 90 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1112, 1054, 1054, + /* 100 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + /* 110 */ 1054, 856, 874, 874, 874, 874, 874, 134, 147, 93, + /* 120 */ 342, 959, 1161, 253, 253, 342, 367, 367, 367, 367, + /* 130 */ 179, 36, 79, 1657, 1657, 1657, 1061, 1061, 1061, 516, + /* 140 */ 799, 516, 516, 531, 531, 802, 249, 369, 342, 342, + /* 150 */ 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + /* 160 */ 342, 342, 342, 342, 342, 342, 342, 342, 342, 272, + /* 170 */ 442, 442, 536, 1657, 1657, 1657, 1025, 245, 245, 570, + /* 180 */ 172, 286, 805, 1047, 1140, 1220, 342, 342, 342, 342, + /* 190 */ 342, 342, 342, 342, 170, 342, 342, 342, 342, 342, + /* 200 */ 342, 342, 342, 342, 342, 342, 342, 841, 841, 841, + /* 210 */ 342, 342, 342, 342, 530, 342, 342, 342, 1059, 342, + /* 220 */ 342, 1167, 342, 342, 342, 342, 342, 342, 342, 342, + /* 230 */ 123, 688, 177, 1212, 1212, 1212, 1212, 1144, 177, 177, + /* 240 */ 1064, 409, 33, 628, 707, 707, 900, 628, 628, 900, + /* 250 */ 897, 323, 398, 677, 677, 677, 707, 572, 684, 590, + /* 260 */ 739, 1236, 1182, 1182, 1276, 1276, 1182, 1253, 1325, 1315, + /* 270 */ 1239, 1346, 1346, 1346, 1346, 1182, 1369, 1239, 1239, 1253, + /* 280 */ 1325, 1315, 1315, 1239, 1182, 1369, 1298, 1376, 1182, 1369, + /* 290 */ 1424, 1182, 1369, 1182, 1369, 1424, 1358, 1358, 1358, 1405, + /* 300 */ 1424, 1358, 1364, 1358, 1405, 1358, 1358, 1424, 1379, 1379, + /* 310 */ 1424, 1351, 1388, 1351, 1388, 1351, 1388, 1351, 1388, 1182, + /* 320 */ 1472, 1182, 1360, 1372, 1377, 1374, 1378, 1239, 1480, 1482, + /* 330 */ 1497, 1497, 1508, 1508, 1508, 1657, 1657, 1657, 1657, 1657, + /* 340 */ 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, + /* 350 */ 1657, 20, 413, 98, 423, 519, 383, 962, 742, 61, + /* 360 */ 696, 749, 750, 753, 789, 790, 795, 797, 840, 842, + /* 370 */ 810, 668, 817, 659, 819, 849, 854, 899, 643, 745, + /* 380 */ 956, 926, 916, 1523, 1529, 1511, 1391, 1521, 1458, 1525, + /* 390 */ 1519, 1520, 1423, 1414, 1436, 1526, 1425, 1531, 1426, 1537, + /* 400 */ 1553, 1431, 1427, 1444, 1496, 1522, 1429, 1505, 1509, 1510, + /* 410 */ 1512, 1452, 1468, 1535, 1447, 1570, 1567, 1551, 1477, 1433, + /* 420 */ 1513, 1550, 1514, 1502, 1538, 1455, 1483, 1559, 1564, 1566, + /* 430 */ 1473, 1481, 1565, 1524, 1568, 1571, 1569, 1572, 1528, 1561, + /* 440 */ 1574, 1530, 1562, 1575, 1577, 1578, 1576, 1580, 1582, 1581, + /* 450 */ 1583, 1585, 1584, 1486, 1587, 1588, 1515, 1586, 1590, 1489, + /* 460 */ 1589, 1591, 1592, 1593, 1594, 1596, 1598, 1589, 1599, 1600, + /* 470 */ 1602, 1601, 1604, 1605, 1607, 1608, 1609, 1610, 1612, 1613, + /* 480 */ 1615, 1614, 1518, 1516, 1527, 1532, 1533, 1618, 1616, 1637, }; -#define YY_REDUCE_USE_DFLT (-144) -#define YY_REDUCE_COUNT (323) -#define YY_REDUCE_MIN (-143) -#define YY_REDUCE_MAX (1305) +#define YY_REDUCE_COUNT (350) +#define YY_REDUCE_MIN (-225) +#define YY_REDUCE_MAX (1375) static const short yy_reduce_ofst[] = { - /* 0 */ -143, -65, 140, 840, 76, 180, 182, 233, 488, -25, - /* 10 */ 12, 16, 59, 885, 907, 935, 390, 705, 954, 285, - /* 20 */ 997, 1017, 1018, -118, 1025, 139, 171, 171, 171, 171, - /* 30 */ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - /* 40 */ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - /* 50 */ 171, 171, 171, 171, 171, 171, 171, 171, -69, 287, - /* 60 */ 441, 658, 708, 856, 1050, 1073, 1076, 1079, 1081, 1084, - /* 70 */ 1086, 1088, 1091, 1113, 1115, 1117, 1122, 1124, 1126, 1128, - /* 80 */ 1130, 1141, 1153, 1156, 1159, 1163, 1165, 1167, 1170, 1172, - /* 90 */ 1175, 1178, 1181, 1189, 1194, 1197, 1200, 1203, 1205, 1207, - /* 100 */ 1211, 1213, 1216, 1219, 171, 171, 171, 171, 171, 171, - /* 110 */ 171, 171, 171, 49, 176, 220, 275, 278, 290, 171, - /* 120 */ 300, 171, 171, 171, 171, -85, -85, -85, -28, 77, - /* 130 */ 313, 317, -56, 252, 252, 446, -129, 243, 361, 403, - /* 140 */ 406, 513, 517, 409, 502, 518, 504, 509, 621, 553, - /* 150 */ 562, 619, 559, 93, 620, 465, 453, 550, 591, 571, - /* 160 */ 615, 666, 750, 752, 797, 819, 463, 548, -73, 28, - /* 170 */ 68, 120, 257, 206, 359, 405, 413, 452, 457, 560, - /* 180 */ 566, 617, 670, 720, 723, 769, 773, 775, 780, 813, - /* 190 */ 814, 821, 822, 823, 826, 360, 436, 783, 829, 835, - /* 200 */ 707, 862, 867, 878, 830, 911, 915, 883, 936, 937, - /* 210 */ 940, 359, 942, 943, 944, 979, 982, 984, 886, 899, - /* 220 */ 928, 929, 931, 707, 947, 945, 998, 949, 932, 969, - /* 230 */ 918, 953, 924, 992, 1005, 1010, 1016, 971, 965, 1019, - /* 240 */ 1049, 1000, 1028, 1074, 989, 1078, 1080, 1026, 1031, 1109, - /* 250 */ 1053, 1090, 1103, 1092, 1099, 1114, 1118, 1148, 1151, 1111, - /* 260 */ 1096, 1129, 1131, 1133, 1162, 1202, 1138, 1146, 1231, 1234, - /* 270 */ 1206, 1218, 1237, 1239, 1240, 1242, 1221, 1228, 1229, 1230, - /* 280 */ 1224, 1233, 1235, 1236, 1241, 1226, 1243, 1244, 1198, 1201, - /* 290 */ 1209, 1212, 1210, 1214, 1215, 1217, 1260, 1199, 1262, 1220, - /* 300 */ 1247, 1222, 1223, 1253, 1238, 1245, 1251, 1246, 1249, 1276, - /* 310 */ 1279, 1289, 1291, 1296, 1302, 1305, 1225, 1227, 1248, 1290, - /* 320 */ 1292, 1280, 1281, 1295, + /* 0 */ -137, -31, 1104, 1023, 1081, -132, -40, -38, 223, 225, + /* 10 */ 698, -153, -99, -225, -165, 386, 478, 843, 859, -139, + /* 20 */ 884, 117, 277, 844, 857, 964, 559, 561, 614, 918, + /* 30 */ 1009, 1089, 1098, -222, -222, -222, -222, -222, -222, -222, + /* 40 */ -222, -222, -222, -222, -222, -222, -222, -222, -222, -222, + /* 50 */ -222, -222, -222, -222, -222, -222, -222, -222, -222, -222, + /* 60 */ -222, -222, -222, -222, -222, 329, 331, 497, 654, 656, + /* 70 */ 781, 891, 946, 1029, 1129, 1134, 1149, 1154, 1160, 1162, + /* 80 */ 1164, 1168, 1174, 1177, 1188, 1191, 1193, 1202, 1204, 1206, + /* 90 */ 1208, 1216, 1218, 1221, 1231, 1233, 1235, 1241, 1244, 1246, + /* 100 */ 1248, 1250, 1258, 1260, 1275, 1277, 1283, 1286, 1288, 1290, + /* 110 */ 1292, -222, -222, -222, -222, -222, -222, -222, -222, -222, + /* 120 */ -115, 796, -156, -154, -141, 14, 242, 349, 242, 349, + /* 130 */ -61, -222, -222, -222, -222, -222, 101, 101, 101, 332, + /* 140 */ 302, 384, 387, -170, 146, 344, 196, 196, 15, 11, + /* 150 */ 183, 235, 395, 355, 396, 406, 452, 457, 391, 459, + /* 160 */ 443, 447, 511, 495, 454, 512, 505, 571, 498, 532, + /* 170 */ 431, 435, 339, 455, 446, 508, -174, -116, -97, -120, + /* 180 */ -150, 64, 176, 330, 337, 509, 569, 611, 653, 673, + /* 190 */ 714, 717, 763, 771, -34, 779, 786, 830, 846, 860, + /* 200 */ 866, 882, 883, 890, 892, 895, 902, 319, 368, 769, + /* 210 */ 915, 924, 925, 932, 755, 936, 945, 963, 782, 969, + /* 220 */ 974, 816, 977, 64, 982, 983, 1016, 1022, 1024, 1031, + /* 230 */ 870, 831, 913, 966, 973, 981, 984, 755, 913, 913, + /* 240 */ 1000, 1041, 1063, 1015, 1010, 1011, 985, 1034, 1057, 1019, + /* 250 */ 1086, 1080, 1085, 1093, 1095, 1096, 1067, 1048, 1082, 1099, + /* 260 */ 1137, 1050, 1150, 1156, 1077, 1088, 1180, 1120, 1132, 1169, + /* 270 */ 1170, 1178, 1181, 1195, 1210, 1225, 1243, 1197, 1209, 1173, + /* 280 */ 1190, 1226, 1238, 1223, 1267, 1272, 1199, 1207, 1282, 1285, + /* 290 */ 1269, 1293, 1295, 1296, 1300, 1289, 1294, 1297, 1299, 1287, + /* 300 */ 1301, 1302, 1303, 1306, 1304, 1307, 1308, 1310, 1242, 1245, + /* 310 */ 1311, 1268, 1270, 1273, 1278, 1274, 1279, 1280, 1284, 1333, + /* 320 */ 1271, 1337, 1281, 1309, 1305, 1312, 1314, 1316, 1344, 1347, + /* 330 */ 1359, 1361, 1368, 1370, 1371, 1291, 1313, 1317, 1355, 1352, + /* 340 */ 1353, 1354, 1356, 1363, 1350, 1357, 1362, 1366, 1367, 1375, + /* 350 */ 1365, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1270, 1260, 1260, 1260, 1193, 1193, 1193, 1193, 1260, 1088, - /* 10 */ 1117, 1117, 1244, 1322, 1322, 1322, 1322, 1322, 1322, 1192, - /* 20 */ 1322, 1322, 1322, 1322, 1260, 1092, 1123, 1322, 1322, 1322, - /* 30 */ 1322, 1194, 1195, 1322, 1322, 1322, 1243, 1245, 1133, 1132, - /* 40 */ 1131, 1130, 1226, 1104, 1128, 1121, 1125, 1194, 1188, 1189, - /* 50 */ 1187, 1191, 1195, 1322, 1124, 1158, 1172, 1157, 1322, 1322, - /* 60 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 70 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 100 */ 1322, 1322, 1322, 1322, 1166, 1171, 1178, 1170, 1167, 1160, - /* 110 */ 1159, 1161, 1162, 1322, 1011, 1059, 1322, 1322, 1322, 1163, - /* 120 */ 1322, 1164, 1175, 1174, 1173, 1251, 1278, 1277, 1322, 1322, - /* 130 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 140 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 150 */ 1322, 1322, 1322, 1322, 1322, 1270, 1260, 1017, 1017, 1322, - /* 160 */ 1260, 1260, 1260, 1260, 1260, 1260, 1256, 1092, 1083, 1322, - /* 170 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 180 */ 1248, 1246, 1322, 1208, 1322, 1322, 1322, 1322, 1322, 1322, - /* 190 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 200 */ 1322, 1322, 1322, 1322, 1088, 1322, 1322, 1322, 1322, 1322, - /* 210 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1272, 1322, 1221, - /* 220 */ 1088, 1088, 1088, 1090, 1072, 1082, 997, 1127, 1106, 1106, - /* 230 */ 1311, 1127, 1311, 1034, 1292, 1031, 1117, 1106, 1190, 1117, - /* 240 */ 1117, 1089, 1082, 1322, 1314, 1097, 1097, 1313, 1313, 1097, - /* 250 */ 1138, 1062, 1127, 1068, 1068, 1068, 1068, 1097, 1008, 1127, - /* 260 */ 1138, 1062, 1062, 1127, 1097, 1008, 1225, 1308, 1097, 1097, - /* 270 */ 1008, 1201, 1097, 1008, 1097, 1008, 1201, 1060, 1060, 1060, - /* 280 */ 1049, 1201, 1060, 1034, 1060, 1049, 1060, 1060, 1110, 1105, - /* 290 */ 1110, 1105, 1110, 1105, 1110, 1105, 1097, 1196, 1097, 1322, - /* 300 */ 1201, 1205, 1205, 1201, 1122, 1111, 1120, 1118, 1127, 1014, - /* 310 */ 1052, 1275, 1275, 1271, 1271, 1271, 1319, 1319, 1256, 1287, - /* 320 */ 1287, 1036, 1036, 1287, 1322, 1322, 1322, 1322, 1322, 1322, - /* 330 */ 1282, 1322, 1210, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 340 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 350 */ 1322, 1143, 1322, 993, 1253, 1322, 1322, 1252, 1322, 1322, - /* 360 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 370 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1310, 1322, - /* 380 */ 1322, 1322, 1322, 1322, 1322, 1224, 1223, 1322, 1322, 1322, - /* 390 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 400 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, - /* 410 */ 1074, 1322, 1322, 1322, 1296, 1322, 1322, 1322, 1322, 1322, - /* 420 */ 1322, 1322, 1119, 1322, 1112, 1322, 1322, 1301, 1322, 1322, - /* 430 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1262, 1322, - /* 440 */ 1322, 1322, 1261, 1322, 1322, 1322, 1322, 1322, 1145, 1322, - /* 450 */ 1144, 1148, 1322, 1002, 1322, + /* 0 */ 1389, 1389, 1389, 1261, 1046, 1151, 1261, 1261, 1261, 1261, + /* 10 */ 1046, 1181, 1181, 1312, 1077, 1046, 1046, 1046, 1046, 1046, + /* 20 */ 1046, 1260, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 30 */ 1046, 1046, 1046, 1187, 1046, 1046, 1046, 1046, 1262, 1263, + /* 40 */ 1046, 1046, 1046, 1311, 1313, 1197, 1196, 1195, 1194, 1294, + /* 50 */ 1168, 1192, 1185, 1189, 1256, 1257, 1255, 1259, 1262, 1263, + /* 60 */ 1046, 1188, 1226, 1240, 1225, 1046, 1046, 1046, 1046, 1046, + /* 70 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 80 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 90 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 100 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 110 */ 1046, 1234, 1239, 1246, 1238, 1235, 1228, 1227, 1229, 1230, + /* 120 */ 1046, 1067, 1116, 1046, 1046, 1046, 1329, 1328, 1046, 1046, + /* 130 */ 1077, 1231, 1232, 1243, 1242, 1241, 1319, 1345, 1344, 1046, + /* 140 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 150 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 160 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1077, + /* 170 */ 1073, 1073, 1046, 1324, 1151, 1142, 1046, 1046, 1046, 1046, + /* 180 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1316, 1314, 1046, + /* 190 */ 1276, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 200 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 210 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1147, 1046, + /* 220 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1339, + /* 230 */ 1046, 1289, 1130, 1147, 1147, 1147, 1147, 1149, 1131, 1129, + /* 240 */ 1141, 1077, 1053, 1191, 1170, 1170, 1378, 1191, 1191, 1378, + /* 250 */ 1091, 1359, 1088, 1181, 1181, 1181, 1170, 1258, 1148, 1141, + /* 260 */ 1046, 1381, 1156, 1156, 1380, 1380, 1156, 1200, 1206, 1119, + /* 270 */ 1191, 1125, 1125, 1125, 1125, 1156, 1064, 1191, 1191, 1200, + /* 280 */ 1206, 1119, 1119, 1191, 1156, 1064, 1293, 1375, 1156, 1064, + /* 290 */ 1269, 1156, 1064, 1156, 1064, 1269, 1117, 1117, 1117, 1106, + /* 300 */ 1269, 1117, 1091, 1117, 1106, 1117, 1117, 1269, 1273, 1273, + /* 310 */ 1269, 1174, 1169, 1174, 1169, 1174, 1169, 1174, 1169, 1156, + /* 320 */ 1264, 1156, 1046, 1186, 1175, 1184, 1182, 1191, 1070, 1109, + /* 330 */ 1342, 1342, 1338, 1338, 1338, 1386, 1386, 1324, 1354, 1077, + /* 340 */ 1077, 1077, 1077, 1354, 1093, 1093, 1077, 1077, 1077, 1077, + /* 350 */ 1354, 1046, 1046, 1046, 1046, 1046, 1046, 1349, 1046, 1278, + /* 360 */ 1160, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 370 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 380 */ 1046, 1046, 1211, 1046, 1049, 1321, 1046, 1046, 1320, 1046, + /* 390 */ 1046, 1046, 1046, 1046, 1046, 1161, 1046, 1046, 1046, 1046, + /* 400 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 410 */ 1046, 1046, 1046, 1046, 1377, 1046, 1046, 1046, 1046, 1046, + /* 420 */ 1046, 1292, 1291, 1046, 1046, 1158, 1046, 1046, 1046, 1046, + /* 430 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 440 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 450 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 460 */ 1183, 1046, 1176, 1046, 1046, 1046, 1046, 1368, 1046, 1046, + /* 470 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + /* 480 */ 1046, 1363, 1133, 1213, 1046, 1212, 1216, 1046, 1058, 1046, }; /********** End of lemon-generated parsing tables *****************************/ @@ -137845,6 +142298,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* ESCAPE => nothing */ 0, /* ID => nothing */ 59, /* COLUMNKW => ID */ + 59, /* DO => ID */ 59, /* FOR => ID */ 59, /* IGNORE => ID */ 59, /* INITIALLY => ID */ @@ -137906,6 +142360,7 @@ struct yyParser { int yyerrcnt; /* Shifts left before out of the error */ #endif sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ + sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ @@ -137949,75 +142404,267 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ } #endif /* NDEBUG */ -#ifndef NDEBUG +#if defined(YYCOVERAGE) || !defined(NDEBUG) /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { - "$", "SEMI", "EXPLAIN", "QUERY", - "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", - "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", - "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", - "TABLE", "CREATE", "IF", "NOT", - "EXISTS", "TEMP", "LP", "RP", - "AS", "WITHOUT", "COMMA", "ABORT", - "ACTION", "AFTER", "ANALYZE", "ASC", - "ATTACH", "BEFORE", "BY", "CASCADE", - "CAST", "CONFLICT", "DATABASE", "DESC", - "DETACH", "EACH", "FAIL", "OR", - "AND", "IS", "MATCH", "LIKE_KW", - "BETWEEN", "IN", "ISNULL", "NOTNULL", - "NE", "EQ", "GT", "LE", - "LT", "GE", "ESCAPE", "ID", - "COLUMNKW", "FOR", "IGNORE", "INITIALLY", - "INSTEAD", "NO", "KEY", "OF", - "OFFSET", "PRAGMA", "RAISE", "RECURSIVE", - "REPLACE", "RESTRICT", "ROW", "TRIGGER", - "VACUUM", "VIEW", "VIRTUAL", "WITH", - "REINDEX", "RENAME", "CTIME_KW", "ANY", - "BITAND", "BITOR", "LSHIFT", "RSHIFT", - "PLUS", "MINUS", "STAR", "SLASH", - "REM", "CONCAT", "COLLATE", "BITNOT", - "INDEXED", "STRING", "JOIN_KW", "CONSTRAINT", - "DEFAULT", "NULL", "PRIMARY", "UNIQUE", - "CHECK", "REFERENCES", "AUTOINCR", "ON", - "INSERT", "DELETE", "UPDATE", "SET", - "DEFERRABLE", "FOREIGN", "DROP", "UNION", - "ALL", "EXCEPT", "INTERSECT", "SELECT", - "VALUES", "DISTINCT", "DOT", "FROM", - "JOIN", "USING", "ORDER", "GROUP", - "HAVING", "LIMIT", "WHERE", "INTO", - "FLOAT", "BLOB", "INTEGER", "VARIABLE", - "CASE", "WHEN", "THEN", "ELSE", - "INDEX", "ALTER", "ADD", "error", - "input", "cmdlist", "ecmd", "explain", - "cmdx", "cmd", "transtype", "trans_opt", - "nm", "savepoint_opt", "create_table", "create_table_args", - "createkw", "temp", "ifnotexists", "dbnm", - "columnlist", "conslist_opt", "table_options", "select", - "columnname", "carglist", "typetoken", "typename", - "signed", "plus_num", "minus_num", "ccons", - "term", "expr", "onconf", "sortorder", - "autoinc", "eidlist_opt", "refargs", "defer_subclause", - "refarg", "refact", "init_deferred_pred_opt", "conslist", - "tconscomma", "tcons", "sortlist", "eidlist", - "defer_subclause_opt", "orconf", "resolvetype", "raisetype", - "ifexists", "fullname", "selectnowith", "oneselect", - "with", "multiselect_op", "distinct", "selcollist", - "from", "where_opt", "groupby_opt", "having_opt", - "orderby_opt", "limit_opt", "values", "nexprlist", - "exprlist", "sclp", "as", "seltablist", - "stl_prefix", "joinop", "indexed_opt", "on_opt", - "using_opt", "idlist", "setlist", "insert_cmd", - "idlist_opt", "likeop", "between_op", "in_op", - "paren_exprlist", "case_operand", "case_exprlist", "case_else", - "uniqueflag", "collate", "nmnum", "trigger_decl", - "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", - "when_clause", "trigger_cmd", "trnm", "tridxby", - "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", - "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", - "lp", "anylist", "wqlist", + /* 0 */ "$", + /* 1 */ "SEMI", + /* 2 */ "EXPLAIN", + /* 3 */ "QUERY", + /* 4 */ "PLAN", + /* 5 */ "BEGIN", + /* 6 */ "TRANSACTION", + /* 7 */ "DEFERRED", + /* 8 */ "IMMEDIATE", + /* 9 */ "EXCLUSIVE", + /* 10 */ "COMMIT", + /* 11 */ "END", + /* 12 */ "ROLLBACK", + /* 13 */ "SAVEPOINT", + /* 14 */ "RELEASE", + /* 15 */ "TO", + /* 16 */ "TABLE", + /* 17 */ "CREATE", + /* 18 */ "IF", + /* 19 */ "NOT", + /* 20 */ "EXISTS", + /* 21 */ "TEMP", + /* 22 */ "LP", + /* 23 */ "RP", + /* 24 */ "AS", + /* 25 */ "WITHOUT", + /* 26 */ "COMMA", + /* 27 */ "ABORT", + /* 28 */ "ACTION", + /* 29 */ "AFTER", + /* 30 */ "ANALYZE", + /* 31 */ "ASC", + /* 32 */ "ATTACH", + /* 33 */ "BEFORE", + /* 34 */ "BY", + /* 35 */ "CASCADE", + /* 36 */ "CAST", + /* 37 */ "CONFLICT", + /* 38 */ "DATABASE", + /* 39 */ "DESC", + /* 40 */ "DETACH", + /* 41 */ "EACH", + /* 42 */ "FAIL", + /* 43 */ "OR", + /* 44 */ "AND", + /* 45 */ "IS", + /* 46 */ "MATCH", + /* 47 */ "LIKE_KW", + /* 48 */ "BETWEEN", + /* 49 */ "IN", + /* 50 */ "ISNULL", + /* 51 */ "NOTNULL", + /* 52 */ "NE", + /* 53 */ "EQ", + /* 54 */ "GT", + /* 55 */ "LE", + /* 56 */ "LT", + /* 57 */ "GE", + /* 58 */ "ESCAPE", + /* 59 */ "ID", + /* 60 */ "COLUMNKW", + /* 61 */ "DO", + /* 62 */ "FOR", + /* 63 */ "IGNORE", + /* 64 */ "INITIALLY", + /* 65 */ "INSTEAD", + /* 66 */ "NO", + /* 67 */ "KEY", + /* 68 */ "OF", + /* 69 */ "OFFSET", + /* 70 */ "PRAGMA", + /* 71 */ "RAISE", + /* 72 */ "RECURSIVE", + /* 73 */ "REPLACE", + /* 74 */ "RESTRICT", + /* 75 */ "ROW", + /* 76 */ "TRIGGER", + /* 77 */ "VACUUM", + /* 78 */ "VIEW", + /* 79 */ "VIRTUAL", + /* 80 */ "WITH", + /* 81 */ "REINDEX", + /* 82 */ "RENAME", + /* 83 */ "CTIME_KW", + /* 84 */ "ANY", + /* 85 */ "BITAND", + /* 86 */ "BITOR", + /* 87 */ "LSHIFT", + /* 88 */ "RSHIFT", + /* 89 */ "PLUS", + /* 90 */ "MINUS", + /* 91 */ "STAR", + /* 92 */ "SLASH", + /* 93 */ "REM", + /* 94 */ "CONCAT", + /* 95 */ "COLLATE", + /* 96 */ "BITNOT", + /* 97 */ "ON", + /* 98 */ "INDEXED", + /* 99 */ "STRING", + /* 100 */ "JOIN_KW", + /* 101 */ "CONSTRAINT", + /* 102 */ "DEFAULT", + /* 103 */ "NULL", + /* 104 */ "PRIMARY", + /* 105 */ "UNIQUE", + /* 106 */ "CHECK", + /* 107 */ "REFERENCES", + /* 108 */ "AUTOINCR", + /* 109 */ "INSERT", + /* 110 */ "DELETE", + /* 111 */ "UPDATE", + /* 112 */ "SET", + /* 113 */ "DEFERRABLE", + /* 114 */ "FOREIGN", + /* 115 */ "DROP", + /* 116 */ "UNION", + /* 117 */ "ALL", + /* 118 */ "EXCEPT", + /* 119 */ "INTERSECT", + /* 120 */ "SELECT", + /* 121 */ "VALUES", + /* 122 */ "DISTINCT", + /* 123 */ "DOT", + /* 124 */ "FROM", + /* 125 */ "JOIN", + /* 126 */ "USING", + /* 127 */ "ORDER", + /* 128 */ "GROUP", + /* 129 */ "HAVING", + /* 130 */ "LIMIT", + /* 131 */ "WHERE", + /* 132 */ "INTO", + /* 133 */ "NOTHING", + /* 134 */ "FLOAT", + /* 135 */ "BLOB", + /* 136 */ "INTEGER", + /* 137 */ "VARIABLE", + /* 138 */ "CASE", + /* 139 */ "WHEN", + /* 140 */ "THEN", + /* 141 */ "ELSE", + /* 142 */ "INDEX", + /* 143 */ "ALTER", + /* 144 */ "ADD", + /* 145 */ "input", + /* 146 */ "cmdlist", + /* 147 */ "ecmd", + /* 148 */ "cmdx", + /* 149 */ "explain", + /* 150 */ "cmd", + /* 151 */ "transtype", + /* 152 */ "trans_opt", + /* 153 */ "nm", + /* 154 */ "savepoint_opt", + /* 155 */ "create_table", + /* 156 */ "create_table_args", + /* 157 */ "createkw", + /* 158 */ "temp", + /* 159 */ "ifnotexists", + /* 160 */ "dbnm", + /* 161 */ "columnlist", + /* 162 */ "conslist_opt", + /* 163 */ "table_options", + /* 164 */ "select", + /* 165 */ "columnname", + /* 166 */ "carglist", + /* 167 */ "typetoken", + /* 168 */ "typename", + /* 169 */ "signed", + /* 170 */ "plus_num", + /* 171 */ "minus_num", + /* 172 */ "scanpt", + /* 173 */ "ccons", + /* 174 */ "term", + /* 175 */ "expr", + /* 176 */ "onconf", + /* 177 */ "sortorder", + /* 178 */ "autoinc", + /* 179 */ "eidlist_opt", + /* 180 */ "refargs", + /* 181 */ "defer_subclause", + /* 182 */ "refarg", + /* 183 */ "refact", + /* 184 */ "init_deferred_pred_opt", + /* 185 */ "conslist", + /* 186 */ "tconscomma", + /* 187 */ "tcons", + /* 188 */ "sortlist", + /* 189 */ "eidlist", + /* 190 */ "defer_subclause_opt", + /* 191 */ "orconf", + /* 192 */ "resolvetype", + /* 193 */ "raisetype", + /* 194 */ "ifexists", + /* 195 */ "fullname", + /* 196 */ "selectnowith", + /* 197 */ "oneselect", + /* 198 */ "wqlist", + /* 199 */ "multiselect_op", + /* 200 */ "distinct", + /* 201 */ "selcollist", + /* 202 */ "from", + /* 203 */ "where_opt", + /* 204 */ "groupby_opt", + /* 205 */ "having_opt", + /* 206 */ "orderby_opt", + /* 207 */ "limit_opt", + /* 208 */ "values", + /* 209 */ "nexprlist", + /* 210 */ "exprlist", + /* 211 */ "sclp", + /* 212 */ "as", + /* 213 */ "seltablist", + /* 214 */ "stl_prefix", + /* 215 */ "joinop", + /* 216 */ "indexed_opt", + /* 217 */ "on_opt", + /* 218 */ "using_opt", + /* 219 */ "xfullname", + /* 220 */ "idlist", + /* 221 */ "with", + /* 222 */ "setlist", + /* 223 */ "insert_cmd", + /* 224 */ "idlist_opt", + /* 225 */ "upsert", + /* 226 */ "likeop", + /* 227 */ "between_op", + /* 228 */ "in_op", + /* 229 */ "paren_exprlist", + /* 230 */ "case_operand", + /* 231 */ "case_exprlist", + /* 232 */ "case_else", + /* 233 */ "uniqueflag", + /* 234 */ "collate", + /* 235 */ "nmnum", + /* 236 */ "trigger_decl", + /* 237 */ "trigger_cmd_list", + /* 238 */ "trigger_time", + /* 239 */ "trigger_event", + /* 240 */ "foreach_clause", + /* 241 */ "when_clause", + /* 242 */ "trigger_cmd", + /* 243 */ "trnm", + /* 244 */ "tridxby", + /* 245 */ "database_kw_opt", + /* 246 */ "key_opt", + /* 247 */ "add_column_fullname", + /* 248 */ "kwcolumn_opt", + /* 249 */ "create_vtab", + /* 250 */ "vtabarglist", + /* 251 */ "vtabarg", + /* 252 */ "vtabargtoken", + /* 253 */ "lp", + /* 254 */ "anylist", }; -#endif /* NDEBUG */ +#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. @@ -138051,307 +142698,319 @@ static const char *const yyRuleName[] = { /* 25 */ "typetoken ::= typename LP signed RP", /* 26 */ "typetoken ::= typename LP signed COMMA signed RP", /* 27 */ "typename ::= typename ID|STRING", - /* 28 */ "ccons ::= CONSTRAINT nm", - /* 29 */ "ccons ::= DEFAULT term", - /* 30 */ "ccons ::= DEFAULT LP expr RP", - /* 31 */ "ccons ::= DEFAULT PLUS term", - /* 32 */ "ccons ::= DEFAULT MINUS term", - /* 33 */ "ccons ::= DEFAULT ID|INDEXED", - /* 34 */ "ccons ::= NOT NULL onconf", - /* 35 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 36 */ "ccons ::= UNIQUE onconf", - /* 37 */ "ccons ::= CHECK LP expr RP", - /* 38 */ "ccons ::= REFERENCES nm eidlist_opt refargs", - /* 39 */ "ccons ::= defer_subclause", - /* 40 */ "ccons ::= COLLATE ID|STRING", - /* 41 */ "autoinc ::=", - /* 42 */ "autoinc ::= AUTOINCR", - /* 43 */ "refargs ::=", - /* 44 */ "refargs ::= refargs refarg", - /* 45 */ "refarg ::= MATCH nm", - /* 46 */ "refarg ::= ON INSERT refact", - /* 47 */ "refarg ::= ON DELETE refact", - /* 48 */ "refarg ::= ON UPDATE refact", - /* 49 */ "refact ::= SET NULL", - /* 50 */ "refact ::= SET DEFAULT", - /* 51 */ "refact ::= CASCADE", - /* 52 */ "refact ::= RESTRICT", - /* 53 */ "refact ::= NO ACTION", - /* 54 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 55 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 56 */ "init_deferred_pred_opt ::=", - /* 57 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 58 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 59 */ "conslist_opt ::=", - /* 60 */ "tconscomma ::= COMMA", - /* 61 */ "tcons ::= CONSTRAINT nm", - /* 62 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", - /* 63 */ "tcons ::= UNIQUE LP sortlist RP onconf", - /* 64 */ "tcons ::= CHECK LP expr RP onconf", - /* 65 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", - /* 66 */ "defer_subclause_opt ::=", - /* 67 */ "onconf ::=", - /* 68 */ "onconf ::= ON CONFLICT resolvetype", - /* 69 */ "orconf ::=", - /* 70 */ "orconf ::= OR resolvetype", - /* 71 */ "resolvetype ::= IGNORE", - /* 72 */ "resolvetype ::= REPLACE", - /* 73 */ "cmd ::= DROP TABLE ifexists fullname", - /* 74 */ "ifexists ::= IF EXISTS", - /* 75 */ "ifexists ::=", - /* 76 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", - /* 77 */ "cmd ::= DROP VIEW ifexists fullname", - /* 78 */ "cmd ::= select", - /* 79 */ "select ::= with selectnowith", - /* 80 */ "selectnowith ::= selectnowith multiselect_op oneselect", - /* 81 */ "multiselect_op ::= UNION", - /* 82 */ "multiselect_op ::= UNION ALL", - /* 83 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 84 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 85 */ "values ::= VALUES LP nexprlist RP", - /* 86 */ "values ::= values COMMA LP exprlist RP", - /* 87 */ "distinct ::= DISTINCT", - /* 88 */ "distinct ::= ALL", - /* 89 */ "distinct ::=", - /* 90 */ "sclp ::=", - /* 91 */ "selcollist ::= sclp expr as", - /* 92 */ "selcollist ::= sclp STAR", - /* 93 */ "selcollist ::= sclp nm DOT STAR", - /* 94 */ "as ::= AS nm", - /* 95 */ "as ::=", - /* 96 */ "from ::=", - /* 97 */ "from ::= FROM seltablist", - /* 98 */ "stl_prefix ::= seltablist joinop", - /* 99 */ "stl_prefix ::=", - /* 100 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 101 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", - /* 102 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 103 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 104 */ "dbnm ::=", - /* 105 */ "dbnm ::= DOT nm", - /* 106 */ "fullname ::= nm dbnm", - /* 107 */ "joinop ::= COMMA|JOIN", - /* 108 */ "joinop ::= JOIN_KW JOIN", - /* 109 */ "joinop ::= JOIN_KW nm JOIN", - /* 110 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 111 */ "on_opt ::= ON expr", - /* 112 */ "on_opt ::=", - /* 113 */ "indexed_opt ::=", - /* 114 */ "indexed_opt ::= INDEXED BY nm", - /* 115 */ "indexed_opt ::= NOT INDEXED", - /* 116 */ "using_opt ::= USING LP idlist RP", - /* 117 */ "using_opt ::=", - /* 118 */ "orderby_opt ::=", - /* 119 */ "orderby_opt ::= ORDER BY sortlist", - /* 120 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 121 */ "sortlist ::= expr sortorder", - /* 122 */ "sortorder ::= ASC", - /* 123 */ "sortorder ::= DESC", - /* 124 */ "sortorder ::=", - /* 125 */ "groupby_opt ::=", - /* 126 */ "groupby_opt ::= GROUP BY nexprlist", - /* 127 */ "having_opt ::=", - /* 128 */ "having_opt ::= HAVING expr", - /* 129 */ "limit_opt ::=", - /* 130 */ "limit_opt ::= LIMIT expr", - /* 131 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 132 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 133 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", - /* 134 */ "where_opt ::=", - /* 135 */ "where_opt ::= WHERE expr", - /* 136 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 137 */ "setlist ::= setlist COMMA nm EQ expr", - /* 138 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 139 */ "setlist ::= nm EQ expr", - /* 140 */ "setlist ::= LP idlist RP EQ expr", - /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 143 */ "insert_cmd ::= INSERT orconf", - /* 144 */ "insert_cmd ::= REPLACE", - /* 145 */ "idlist_opt ::=", - /* 146 */ "idlist_opt ::= LP idlist RP", - /* 147 */ "idlist ::= idlist COMMA nm", - /* 148 */ "idlist ::= nm", - /* 149 */ "expr ::= LP expr RP", - /* 150 */ "expr ::= ID|INDEXED", - /* 151 */ "expr ::= JOIN_KW", - /* 152 */ "expr ::= nm DOT nm", - /* 153 */ "expr ::= nm DOT nm DOT nm", - /* 154 */ "term ::= NULL|FLOAT|BLOB", - /* 155 */ "term ::= STRING", - /* 156 */ "term ::= INTEGER", - /* 157 */ "expr ::= VARIABLE", - /* 158 */ "expr ::= expr COLLATE ID|STRING", - /* 159 */ "expr ::= CAST LP expr AS typetoken RP", - /* 160 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 161 */ "expr ::= ID|INDEXED LP STAR RP", - /* 162 */ "term ::= CTIME_KW", - /* 163 */ "expr ::= LP nexprlist COMMA expr RP", - /* 164 */ "expr ::= expr AND expr", - /* 165 */ "expr ::= expr OR expr", - /* 166 */ "expr ::= expr LT|GT|GE|LE expr", - /* 167 */ "expr ::= expr EQ|NE expr", - /* 168 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 169 */ "expr ::= expr PLUS|MINUS expr", - /* 170 */ "expr ::= expr STAR|SLASH|REM expr", - /* 171 */ "expr ::= expr CONCAT expr", - /* 172 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 173 */ "expr ::= expr likeop expr", - /* 174 */ "expr ::= expr likeop expr ESCAPE expr", - /* 175 */ "expr ::= expr ISNULL|NOTNULL", - /* 176 */ "expr ::= expr NOT NULL", - /* 177 */ "expr ::= expr IS expr", - /* 178 */ "expr ::= expr IS NOT expr", - /* 179 */ "expr ::= NOT expr", - /* 180 */ "expr ::= BITNOT expr", - /* 181 */ "expr ::= MINUS expr", - /* 182 */ "expr ::= PLUS expr", - /* 183 */ "between_op ::= BETWEEN", - /* 184 */ "between_op ::= NOT BETWEEN", - /* 185 */ "expr ::= expr between_op expr AND expr", - /* 186 */ "in_op ::= IN", - /* 187 */ "in_op ::= NOT IN", - /* 188 */ "expr ::= expr in_op LP exprlist RP", - /* 189 */ "expr ::= LP select RP", - /* 190 */ "expr ::= expr in_op LP select RP", - /* 191 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 192 */ "expr ::= EXISTS LP select RP", - /* 193 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 194 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 195 */ "case_exprlist ::= WHEN expr THEN expr", - /* 196 */ "case_else ::= ELSE expr", - /* 197 */ "case_else ::=", - /* 198 */ "case_operand ::= expr", - /* 199 */ "case_operand ::=", - /* 200 */ "exprlist ::=", - /* 201 */ "nexprlist ::= nexprlist COMMA expr", - /* 202 */ "nexprlist ::= expr", - /* 203 */ "paren_exprlist ::=", - /* 204 */ "paren_exprlist ::= LP exprlist RP", - /* 205 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 206 */ "uniqueflag ::= UNIQUE", - /* 207 */ "uniqueflag ::=", - /* 208 */ "eidlist_opt ::=", - /* 209 */ "eidlist_opt ::= LP eidlist RP", - /* 210 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 211 */ "eidlist ::= nm collate sortorder", - /* 212 */ "collate ::=", - /* 213 */ "collate ::= COLLATE ID|STRING", - /* 214 */ "cmd ::= DROP INDEX ifexists fullname", - /* 215 */ "cmd ::= VACUUM", - /* 216 */ "cmd ::= VACUUM nm", - /* 217 */ "cmd ::= PRAGMA nm dbnm", - /* 218 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 219 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 220 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 221 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 222 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 223 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 224 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 225 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 226 */ "trigger_time ::= BEFORE|AFTER", - /* 227 */ "trigger_time ::= INSTEAD OF", - /* 228 */ "trigger_time ::=", - /* 229 */ "trigger_event ::= DELETE|INSERT", - /* 230 */ "trigger_event ::= UPDATE", - /* 231 */ "trigger_event ::= UPDATE OF idlist", - /* 232 */ "when_clause ::=", - /* 233 */ "when_clause ::= WHEN expr", - /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 236 */ "trnm ::= nm DOT nm", - /* 237 */ "tridxby ::= INDEXED BY nm", - /* 238 */ "tridxby ::= NOT INDEXED", - /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 242 */ "trigger_cmd ::= select", - /* 243 */ "expr ::= RAISE LP IGNORE RP", - /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 245 */ "raisetype ::= ROLLBACK", - /* 246 */ "raisetype ::= ABORT", - /* 247 */ "raisetype ::= FAIL", - /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 250 */ "cmd ::= DETACH database_kw_opt expr", - /* 251 */ "key_opt ::=", - /* 252 */ "key_opt ::= KEY expr", - /* 253 */ "cmd ::= REINDEX", - /* 254 */ "cmd ::= REINDEX nm dbnm", - /* 255 */ "cmd ::= ANALYZE", - /* 256 */ "cmd ::= ANALYZE nm dbnm", - /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 259 */ "add_column_fullname ::= fullname", - /* 260 */ "cmd ::= create_vtab", - /* 261 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 263 */ "vtabarg ::=", - /* 264 */ "vtabargtoken ::= ANY", - /* 265 */ "vtabargtoken ::= lp anylist RP", - /* 266 */ "lp ::= LP", - /* 267 */ "with ::=", - /* 268 */ "with ::= WITH wqlist", - /* 269 */ "with ::= WITH RECURSIVE wqlist", - /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 272 */ "input ::= cmdlist", - /* 273 */ "cmdlist ::= cmdlist ecmd", - /* 274 */ "cmdlist ::= ecmd", - /* 275 */ "ecmd ::= SEMI", - /* 276 */ "ecmd ::= explain cmdx SEMI", - /* 277 */ "explain ::=", - /* 278 */ "trans_opt ::=", - /* 279 */ "trans_opt ::= TRANSACTION", - /* 280 */ "trans_opt ::= TRANSACTION nm", - /* 281 */ "savepoint_opt ::= SAVEPOINT", - /* 282 */ "savepoint_opt ::=", - /* 283 */ "cmd ::= create_table create_table_args", - /* 284 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 285 */ "columnlist ::= columnname carglist", - /* 286 */ "nm ::= ID|INDEXED", - /* 287 */ "nm ::= STRING", - /* 288 */ "nm ::= JOIN_KW", - /* 289 */ "typetoken ::= typename", - /* 290 */ "typename ::= ID|STRING", - /* 291 */ "signed ::= plus_num", - /* 292 */ "signed ::= minus_num", - /* 293 */ "carglist ::= carglist ccons", - /* 294 */ "carglist ::=", - /* 295 */ "ccons ::= NULL onconf", - /* 296 */ "conslist_opt ::= COMMA conslist", - /* 297 */ "conslist ::= conslist tconscomma tcons", - /* 298 */ "conslist ::= tcons", - /* 299 */ "tconscomma ::=", - /* 300 */ "defer_subclause_opt ::= defer_subclause", - /* 301 */ "resolvetype ::= raisetype", - /* 302 */ "selectnowith ::= oneselect", - /* 303 */ "oneselect ::= values", - /* 304 */ "sclp ::= selcollist COMMA", - /* 305 */ "as ::= ID|STRING", - /* 306 */ "expr ::= term", - /* 307 */ "likeop ::= LIKE_KW|MATCH", - /* 308 */ "exprlist ::= nexprlist", - /* 309 */ "nmnum ::= plus_num", - /* 310 */ "nmnum ::= nm", - /* 311 */ "nmnum ::= ON", - /* 312 */ "nmnum ::= DELETE", - /* 313 */ "nmnum ::= DEFAULT", - /* 314 */ "plus_num ::= INTEGER|FLOAT", - /* 315 */ "foreach_clause ::=", - /* 316 */ "foreach_clause ::= FOR EACH ROW", - /* 317 */ "trnm ::= nm", - /* 318 */ "tridxby ::=", - /* 319 */ "database_kw_opt ::= DATABASE", - /* 320 */ "database_kw_opt ::=", - /* 321 */ "kwcolumn_opt ::=", - /* 322 */ "kwcolumn_opt ::= COLUMNKW", - /* 323 */ "vtabarglist ::= vtabarg", - /* 324 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 325 */ "vtabarg ::= vtabarg vtabargtoken", - /* 326 */ "anylist ::=", - /* 327 */ "anylist ::= anylist LP anylist RP", - /* 328 */ "anylist ::= anylist ANY", + /* 28 */ "scanpt ::=", + /* 29 */ "ccons ::= CONSTRAINT nm", + /* 30 */ "ccons ::= DEFAULT scanpt term scanpt", + /* 31 */ "ccons ::= DEFAULT LP expr RP", + /* 32 */ "ccons ::= DEFAULT PLUS term scanpt", + /* 33 */ "ccons ::= DEFAULT MINUS term scanpt", + /* 34 */ "ccons ::= DEFAULT scanpt ID|INDEXED", + /* 35 */ "ccons ::= NOT NULL onconf", + /* 36 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 37 */ "ccons ::= UNIQUE onconf", + /* 38 */ "ccons ::= CHECK LP expr RP", + /* 39 */ "ccons ::= REFERENCES nm eidlist_opt refargs", + /* 40 */ "ccons ::= defer_subclause", + /* 41 */ "ccons ::= COLLATE ID|STRING", + /* 42 */ "autoinc ::=", + /* 43 */ "autoinc ::= AUTOINCR", + /* 44 */ "refargs ::=", + /* 45 */ "refargs ::= refargs refarg", + /* 46 */ "refarg ::= MATCH nm", + /* 47 */ "refarg ::= ON INSERT refact", + /* 48 */ "refarg ::= ON DELETE refact", + /* 49 */ "refarg ::= ON UPDATE refact", + /* 50 */ "refact ::= SET NULL", + /* 51 */ "refact ::= SET DEFAULT", + /* 52 */ "refact ::= CASCADE", + /* 53 */ "refact ::= RESTRICT", + /* 54 */ "refact ::= NO ACTION", + /* 55 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 56 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 57 */ "init_deferred_pred_opt ::=", + /* 58 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 59 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 60 */ "conslist_opt ::=", + /* 61 */ "tconscomma ::= COMMA", + /* 62 */ "tcons ::= CONSTRAINT nm", + /* 63 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", + /* 64 */ "tcons ::= UNIQUE LP sortlist RP onconf", + /* 65 */ "tcons ::= CHECK LP expr RP onconf", + /* 66 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", + /* 67 */ "defer_subclause_opt ::=", + /* 68 */ "onconf ::=", + /* 69 */ "onconf ::= ON CONFLICT resolvetype", + /* 70 */ "orconf ::=", + /* 71 */ "orconf ::= OR resolvetype", + /* 72 */ "resolvetype ::= IGNORE", + /* 73 */ "resolvetype ::= REPLACE", + /* 74 */ "cmd ::= DROP TABLE ifexists fullname", + /* 75 */ "ifexists ::= IF EXISTS", + /* 76 */ "ifexists ::=", + /* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", + /* 78 */ "cmd ::= DROP VIEW ifexists fullname", + /* 79 */ "cmd ::= select", + /* 80 */ "select ::= WITH wqlist selectnowith", + /* 81 */ "select ::= WITH RECURSIVE wqlist selectnowith", + /* 82 */ "select ::= selectnowith", + /* 83 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 84 */ "multiselect_op ::= UNION", + /* 85 */ "multiselect_op ::= UNION ALL", + /* 86 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 88 */ "values ::= VALUES LP nexprlist RP", + /* 89 */ "values ::= values COMMA LP exprlist RP", + /* 90 */ "distinct ::= DISTINCT", + /* 91 */ "distinct ::= ALL", + /* 92 */ "distinct ::=", + /* 93 */ "sclp ::=", + /* 94 */ "selcollist ::= sclp scanpt expr scanpt as", + /* 95 */ "selcollist ::= sclp scanpt STAR", + /* 96 */ "selcollist ::= sclp scanpt nm DOT STAR", + /* 97 */ "as ::= AS nm", + /* 98 */ "as ::=", + /* 99 */ "from ::=", + /* 100 */ "from ::= FROM seltablist", + /* 101 */ "stl_prefix ::= seltablist joinop", + /* 102 */ "stl_prefix ::=", + /* 103 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", + /* 104 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", + /* 105 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 106 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 107 */ "dbnm ::=", + /* 108 */ "dbnm ::= DOT nm", + /* 109 */ "fullname ::= nm", + /* 110 */ "fullname ::= nm DOT nm", + /* 111 */ "xfullname ::= nm", + /* 112 */ "xfullname ::= nm DOT nm", + /* 113 */ "xfullname ::= nm DOT nm AS nm", + /* 114 */ "xfullname ::= nm AS nm", + /* 115 */ "joinop ::= COMMA|JOIN", + /* 116 */ "joinop ::= JOIN_KW JOIN", + /* 117 */ "joinop ::= JOIN_KW nm JOIN", + /* 118 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 119 */ "on_opt ::= ON expr", + /* 120 */ "on_opt ::=", + /* 121 */ "indexed_opt ::=", + /* 122 */ "indexed_opt ::= INDEXED BY nm", + /* 123 */ "indexed_opt ::= NOT INDEXED", + /* 124 */ "using_opt ::= USING LP idlist RP", + /* 125 */ "using_opt ::=", + /* 126 */ "orderby_opt ::=", + /* 127 */ "orderby_opt ::= ORDER BY sortlist", + /* 128 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 129 */ "sortlist ::= expr sortorder", + /* 130 */ "sortorder ::= ASC", + /* 131 */ "sortorder ::= DESC", + /* 132 */ "sortorder ::=", + /* 133 */ "groupby_opt ::=", + /* 134 */ "groupby_opt ::= GROUP BY nexprlist", + /* 135 */ "having_opt ::=", + /* 136 */ "having_opt ::= HAVING expr", + /* 137 */ "limit_opt ::=", + /* 138 */ "limit_opt ::= LIMIT expr", + /* 139 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 140 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 141 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt", + /* 142 */ "where_opt ::=", + /* 143 */ "where_opt ::= WHERE expr", + /* 144 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt", + /* 145 */ "setlist ::= setlist COMMA nm EQ expr", + /* 146 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 147 */ "setlist ::= nm EQ expr", + /* 148 */ "setlist ::= LP idlist RP EQ expr", + /* 149 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", + /* 150 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES", + /* 151 */ "upsert ::=", + /* 152 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt", + /* 153 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING", + /* 154 */ "upsert ::= ON CONFLICT DO NOTHING", + /* 155 */ "insert_cmd ::= INSERT orconf", + /* 156 */ "insert_cmd ::= REPLACE", + /* 157 */ "idlist_opt ::=", + /* 158 */ "idlist_opt ::= LP idlist RP", + /* 159 */ "idlist ::= idlist COMMA nm", + /* 160 */ "idlist ::= nm", + /* 161 */ "expr ::= LP expr RP", + /* 162 */ "expr ::= ID|INDEXED", + /* 163 */ "expr ::= JOIN_KW", + /* 164 */ "expr ::= nm DOT nm", + /* 165 */ "expr ::= nm DOT nm DOT nm", + /* 166 */ "term ::= NULL|FLOAT|BLOB", + /* 167 */ "term ::= STRING", + /* 168 */ "term ::= INTEGER", + /* 169 */ "expr ::= VARIABLE", + /* 170 */ "expr ::= expr COLLATE ID|STRING", + /* 171 */ "expr ::= CAST LP expr AS typetoken RP", + /* 172 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 173 */ "expr ::= ID|INDEXED LP STAR RP", + /* 174 */ "term ::= CTIME_KW", + /* 175 */ "expr ::= LP nexprlist COMMA expr RP", + /* 176 */ "expr ::= expr AND expr", + /* 177 */ "expr ::= expr OR expr", + /* 178 */ "expr ::= expr LT|GT|GE|LE expr", + /* 179 */ "expr ::= expr EQ|NE expr", + /* 180 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 181 */ "expr ::= expr PLUS|MINUS expr", + /* 182 */ "expr ::= expr STAR|SLASH|REM expr", + /* 183 */ "expr ::= expr CONCAT expr", + /* 184 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 185 */ "expr ::= expr likeop expr", + /* 186 */ "expr ::= expr likeop expr ESCAPE expr", + /* 187 */ "expr ::= expr ISNULL|NOTNULL", + /* 188 */ "expr ::= expr NOT NULL", + /* 189 */ "expr ::= expr IS expr", + /* 190 */ "expr ::= expr IS NOT expr", + /* 191 */ "expr ::= NOT expr", + /* 192 */ "expr ::= BITNOT expr", + /* 193 */ "expr ::= MINUS expr", + /* 194 */ "expr ::= PLUS expr", + /* 195 */ "between_op ::= BETWEEN", + /* 196 */ "between_op ::= NOT BETWEEN", + /* 197 */ "expr ::= expr between_op expr AND expr", + /* 198 */ "in_op ::= IN", + /* 199 */ "in_op ::= NOT IN", + /* 200 */ "expr ::= expr in_op LP exprlist RP", + /* 201 */ "expr ::= LP select RP", + /* 202 */ "expr ::= expr in_op LP select RP", + /* 203 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 204 */ "expr ::= EXISTS LP select RP", + /* 205 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 206 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 207 */ "case_exprlist ::= WHEN expr THEN expr", + /* 208 */ "case_else ::= ELSE expr", + /* 209 */ "case_else ::=", + /* 210 */ "case_operand ::= expr", + /* 211 */ "case_operand ::=", + /* 212 */ "exprlist ::=", + /* 213 */ "nexprlist ::= nexprlist COMMA expr", + /* 214 */ "nexprlist ::= expr", + /* 215 */ "paren_exprlist ::=", + /* 216 */ "paren_exprlist ::= LP exprlist RP", + /* 217 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 218 */ "uniqueflag ::= UNIQUE", + /* 219 */ "uniqueflag ::=", + /* 220 */ "eidlist_opt ::=", + /* 221 */ "eidlist_opt ::= LP eidlist RP", + /* 222 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 223 */ "eidlist ::= nm collate sortorder", + /* 224 */ "collate ::=", + /* 225 */ "collate ::= COLLATE ID|STRING", + /* 226 */ "cmd ::= DROP INDEX ifexists fullname", + /* 227 */ "cmd ::= VACUUM", + /* 228 */ "cmd ::= VACUUM nm", + /* 229 */ "cmd ::= PRAGMA nm dbnm", + /* 230 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 231 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 232 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 233 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 234 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 235 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 236 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 237 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 238 */ "trigger_time ::= BEFORE|AFTER", + /* 239 */ "trigger_time ::= INSTEAD OF", + /* 240 */ "trigger_time ::=", + /* 241 */ "trigger_event ::= DELETE|INSERT", + /* 242 */ "trigger_event ::= UPDATE", + /* 243 */ "trigger_event ::= UPDATE OF idlist", + /* 244 */ "when_clause ::=", + /* 245 */ "when_clause ::= WHEN expr", + /* 246 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 247 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 248 */ "trnm ::= nm DOT nm", + /* 249 */ "tridxby ::= INDEXED BY nm", + /* 250 */ "tridxby ::= NOT INDEXED", + /* 251 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", + /* 252 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 253 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 254 */ "trigger_cmd ::= scanpt select scanpt", + /* 255 */ "expr ::= RAISE LP IGNORE RP", + /* 256 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 257 */ "raisetype ::= ROLLBACK", + /* 258 */ "raisetype ::= ABORT", + /* 259 */ "raisetype ::= FAIL", + /* 260 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 261 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 262 */ "cmd ::= DETACH database_kw_opt expr", + /* 263 */ "key_opt ::=", + /* 264 */ "key_opt ::= KEY expr", + /* 265 */ "cmd ::= REINDEX", + /* 266 */ "cmd ::= REINDEX nm dbnm", + /* 267 */ "cmd ::= ANALYZE", + /* 268 */ "cmd ::= ANALYZE nm dbnm", + /* 269 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 270 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 271 */ "add_column_fullname ::= fullname", + /* 272 */ "cmd ::= create_vtab", + /* 273 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 274 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 275 */ "vtabarg ::=", + /* 276 */ "vtabargtoken ::= ANY", + /* 277 */ "vtabargtoken ::= lp anylist RP", + /* 278 */ "lp ::= LP", + /* 279 */ "with ::= WITH wqlist", + /* 280 */ "with ::= WITH RECURSIVE wqlist", + /* 281 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 282 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 283 */ "input ::= cmdlist", + /* 284 */ "cmdlist ::= cmdlist ecmd", + /* 285 */ "cmdlist ::= ecmd", + /* 286 */ "ecmd ::= SEMI", + /* 287 */ "ecmd ::= cmdx SEMI", + /* 288 */ "ecmd ::= explain cmdx", + /* 289 */ "trans_opt ::=", + /* 290 */ "trans_opt ::= TRANSACTION", + /* 291 */ "trans_opt ::= TRANSACTION nm", + /* 292 */ "savepoint_opt ::= SAVEPOINT", + /* 293 */ "savepoint_opt ::=", + /* 294 */ "cmd ::= create_table create_table_args", + /* 295 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 296 */ "columnlist ::= columnname carglist", + /* 297 */ "nm ::= ID|INDEXED", + /* 298 */ "nm ::= STRING", + /* 299 */ "nm ::= JOIN_KW", + /* 300 */ "typetoken ::= typename", + /* 301 */ "typename ::= ID|STRING", + /* 302 */ "signed ::= plus_num", + /* 303 */ "signed ::= minus_num", + /* 304 */ "carglist ::= carglist ccons", + /* 305 */ "carglist ::=", + /* 306 */ "ccons ::= NULL onconf", + /* 307 */ "conslist_opt ::= COMMA conslist", + /* 308 */ "conslist ::= conslist tconscomma tcons", + /* 309 */ "conslist ::= tcons", + /* 310 */ "tconscomma ::=", + /* 311 */ "defer_subclause_opt ::= defer_subclause", + /* 312 */ "resolvetype ::= raisetype", + /* 313 */ "selectnowith ::= oneselect", + /* 314 */ "oneselect ::= values", + /* 315 */ "sclp ::= selcollist COMMA", + /* 316 */ "as ::= ID|STRING", + /* 317 */ "expr ::= term", + /* 318 */ "likeop ::= LIKE_KW|MATCH", + /* 319 */ "exprlist ::= nexprlist", + /* 320 */ "nmnum ::= plus_num", + /* 321 */ "nmnum ::= nm", + /* 322 */ "nmnum ::= ON", + /* 323 */ "nmnum ::= DELETE", + /* 324 */ "nmnum ::= DEFAULT", + /* 325 */ "plus_num ::= INTEGER|FLOAT", + /* 326 */ "foreach_clause ::=", + /* 327 */ "foreach_clause ::= FOR EACH ROW", + /* 328 */ "trnm ::= nm", + /* 329 */ "tridxby ::=", + /* 330 */ "database_kw_opt ::= DATABASE", + /* 331 */ "database_kw_opt ::=", + /* 332 */ "kwcolumn_opt ::=", + /* 333 */ "kwcolumn_opt ::= COLUMNKW", + /* 334 */ "vtabarglist ::= vtabarg", + /* 335 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 336 */ "vtabarg ::= vtabarg vtabargtoken", + /* 337 */ "anylist ::=", + /* 338 */ "anylist ::= anylist LP anylist RP", + /* 339 */ "anylist ::= anylist ANY", + /* 340 */ "with ::=", }; #endif /* NDEBUG */ @@ -138400,28 +143059,29 @@ static int yyGrowStack(yyParser *p){ /* Initialize a new parser that has already been allocated. */ -SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ - yyParser *pParser = (yyParser*)yypParser; +SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL){ + yyParser *yypParser = (yyParser*)yypRawParser; + sqlite3ParserCTX_STORE #ifdef YYTRACKMAXSTACKDEPTH - pParser->yyhwm = 0; + yypParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 - pParser->yytos = NULL; - pParser->yystack = NULL; - pParser->yystksz = 0; - if( yyGrowStack(pParser) ){ - pParser->yystack = &pParser->yystk0; - pParser->yystksz = 1; + yypParser->yytos = NULL; + yypParser->yystack = NULL; + yypParser->yystksz = 0; + if( yyGrowStack(yypParser) ){ + yypParser->yystack = &yypParser->yystk0; + yypParser->yystksz = 1; } #endif #ifndef YYNOERRORRECOVERY - pParser->yyerrcnt = -1; + yypParser->yyerrcnt = -1; #endif - pParser->yytos = pParser->yystack; - pParser->yystack[0].stateno = 0; - pParser->yystack[0].major = 0; + yypParser->yytos = yypParser->yystack; + yypParser->yystack[0].stateno = 0; + yypParser->yystack[0].major = 0; #if YYSTACKDEPTH>0 - pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; + yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #endif } @@ -138438,11 +143098,14 @@ SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ ** A pointer to a parser. This pointer is used in subsequent calls ** to sqlite3Parser and sqlite3ParserFree. */ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( pParser ) sqlite3ParserInit(pParser); - return pParser; +SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) sqlite3ParserCTX_PDECL){ + yyParser *yypParser; + yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( yypParser ){ + sqlite3ParserCTX_STORE + sqlite3ParserInit(yypParser sqlite3ParserCTX_PARAM); + } + return (void*)yypParser; } #endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ @@ -138459,7 +143122,8 @@ static void yy_destructor( YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ - sqlite3ParserARG_FETCH; + sqlite3ParserARG_FETCH + sqlite3ParserCTX_FETCH switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -138472,77 +143136,73 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 163: /* select */ - case 194: /* selectnowith */ - case 195: /* oneselect */ - case 206: /* values */ + case 164: /* select */ + case 196: /* selectnowith */ + case 197: /* oneselect */ + case 208: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy243)); +sqlite3SelectDelete(pParse->db, (yypminor->yy399)); } break; - case 172: /* term */ - case 173: /* expr */ + case 174: /* term */ + case 175: /* expr */ + case 203: /* where_opt */ + case 205: /* having_opt */ + case 217: /* on_opt */ + case 230: /* case_operand */ + case 232: /* case_else */ + case 241: /* when_clause */ + case 246: /* key_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy190).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy182)); } break; - case 177: /* eidlist_opt */ - case 186: /* sortlist */ - case 187: /* eidlist */ - case 199: /* selcollist */ - case 202: /* groupby_opt */ - case 204: /* orderby_opt */ - case 207: /* nexprlist */ - case 208: /* exprlist */ - case 209: /* sclp */ - case 218: /* setlist */ - case 224: /* paren_exprlist */ - case 226: /* case_exprlist */ + case 179: /* eidlist_opt */ + case 188: /* sortlist */ + case 189: /* eidlist */ + case 201: /* selcollist */ + case 204: /* groupby_opt */ + case 206: /* orderby_opt */ + case 209: /* nexprlist */ + case 210: /* exprlist */ + case 211: /* sclp */ + case 222: /* setlist */ + case 229: /* paren_exprlist */ + case 231: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy148)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy232)); } break; - case 193: /* fullname */ - case 200: /* from */ - case 211: /* seltablist */ - case 212: /* stl_prefix */ + case 195: /* fullname */ + case 202: /* from */ + case 213: /* seltablist */ + case 214: /* stl_prefix */ + case 219: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy185)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy427)); } break; - case 196: /* with */ - case 250: /* wqlist */ + case 198: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy285)); +sqlite3WithDelete(pParse->db, (yypminor->yy91)); } break; - case 201: /* where_opt */ - case 203: /* having_opt */ - case 215: /* on_opt */ - case 225: /* case_operand */ - case 227: /* case_else */ - case 236: /* when_clause */ - case 241: /* key_opt */ + case 218: /* using_opt */ + case 220: /* idlist */ + case 224: /* idlist_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy72)); +sqlite3IdListDelete(pParse->db, (yypminor->yy510)); } break; - case 216: /* using_opt */ - case 217: /* idlist */ - case 220: /* idlist_opt */ + case 237: /* trigger_cmd_list */ + case 242: /* trigger_cmd */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy254)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy47)); } break; - case 232: /* trigger_cmd_list */ - case 237: /* trigger_cmd */ + case 239: /* trigger_event */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy145)); -} - break; - case 234: /* trigger_event */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy332).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy300).b); } break; /********* End destructor definitions *****************************************/ @@ -138613,24 +143273,66 @@ SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){ } #endif +/* This array of booleans keeps track of the parser statement +** coverage. The element yycoverage[X][Y] is set when the parser +** is in state X and has a lookahead token Y. In a well-tested +** systems, every element of this matrix should end up being set. +*/ +#if defined(YYCOVERAGE) +static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; +#endif + +/* +** Write into out a description of every state/lookahead combination that +** +** (1) has not been used by the parser, and +** (2) is not a syntax error. +** +** Return the number of missed state/lookahead combinations. +*/ +#if defined(YYCOVERAGE) +SQLITE_PRIVATE int sqlite3ParserCoverage(FILE *out){ + int stateno, iLookAhead, i; + int nMissed = 0; + for(stateno=0; statenoyytos->stateno; - - if( stateno>=YY_MIN_REDUCE ) return stateno; + + if( stateno>YY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); +#if defined(YYCOVERAGE) + yycoverage[stateno][iLookAhead] = 1; +#endif do{ i = yy_shift_ofst[stateno]; + assert( i>=0 ); + assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); assert( iLookAhead!=YYNOCODE ); + assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ if( iLookAheadyytos->major], + fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], yyNewState); }else{ - fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yytos->major]); + fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], + yyNewState - YY_MIN_REDUCE); } } } #else -# define yyTraceShift(X,Y) +# define yyTraceShift(X,Y,Z) #endif /* @@ -138752,8 +143456,8 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){ */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ - int yyNewState, /* The new state to shift in */ - int yyMajor, /* The major token to shift in */ + YYACTIONTYPE yyNewState, /* The new state to shift in */ + YYCODETYPE yyMajor, /* The major token to shift in */ sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; @@ -138783,10 +143487,10 @@ static void yy_shift( yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } yytos = yypParser->yytos; - yytos->stateno = (YYACTIONTYPE)yyNewState; - yytos->major = (YYCODETYPE)yyMajor; + yytos->stateno = yyNewState; + yytos->major = yyMajor; yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState); + yyTraceShift(yypParser, yyNewState, "Shift"); } /* The following table contains information about every rule that @@ -138796,335 +143500,347 @@ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ signed char nrhs; /* Negative of the number of RHS symbols in the rule */ } yyRuleInfo[] = { - { 147, -1 }, - { 147, -3 }, - { 148, -1 }, - { 149, -3 }, - { 150, 0 }, - { 150, -1 }, - { 150, -1 }, - { 150, -1 }, - { 149, -2 }, - { 149, -2 }, - { 149, -2 }, - { 149, -3 }, - { 149, -5 }, - { 154, -6 }, - { 156, -1 }, - { 158, 0 }, - { 158, -3 }, - { 157, -1 }, - { 157, 0 }, - { 155, -5 }, - { 155, -2 }, - { 162, 0 }, - { 162, -2 }, - { 164, -2 }, - { 166, 0 }, - { 166, -4 }, - { 166, -6 }, - { 167, -2 }, - { 171, -2 }, - { 171, -2 }, - { 171, -4 }, - { 171, -3 }, - { 171, -3 }, - { 171, -2 }, - { 171, -3 }, - { 171, -5 }, - { 171, -2 }, - { 171, -4 }, - { 171, -4 }, - { 171, -1 }, - { 171, -2 }, - { 176, 0 }, - { 176, -1 }, - { 178, 0 }, - { 178, -2 }, - { 180, -2 }, - { 180, -3 }, - { 180, -3 }, - { 180, -3 }, - { 181, -2 }, - { 181, -2 }, - { 181, -1 }, - { 181, -1 }, - { 181, -2 }, - { 179, -3 }, - { 179, -2 }, - { 182, 0 }, - { 182, -2 }, - { 182, -2 }, - { 161, 0 }, - { 184, -1 }, - { 185, -2 }, - { 185, -7 }, - { 185, -5 }, - { 185, -5 }, - { 185, -10 }, - { 188, 0 }, - { 174, 0 }, - { 174, -3 }, - { 189, 0 }, - { 189, -2 }, - { 190, -1 }, - { 190, -1 }, - { 149, -4 }, - { 192, -2 }, - { 192, 0 }, - { 149, -9 }, - { 149, -4 }, - { 149, -1 }, - { 163, -2 }, - { 194, -3 }, - { 197, -1 }, - { 197, -2 }, - { 197, -1 }, - { 195, -9 }, - { 206, -4 }, - { 206, -5 }, - { 198, -1 }, - { 198, -1 }, - { 198, 0 }, - { 209, 0 }, - { 199, -3 }, - { 199, -2 }, - { 199, -4 }, - { 210, -2 }, - { 210, 0 }, - { 200, 0 }, - { 200, -2 }, - { 212, -2 }, - { 212, 0 }, - { 211, -7 }, - { 211, -9 }, - { 211, -7 }, - { 211, -7 }, - { 159, 0 }, - { 159, -2 }, - { 193, -2 }, - { 213, -1 }, - { 213, -2 }, - { 213, -3 }, - { 213, -4 }, - { 215, -2 }, - { 215, 0 }, - { 214, 0 }, - { 214, -3 }, - { 214, -2 }, - { 216, -4 }, - { 216, 0 }, - { 204, 0 }, - { 204, -3 }, - { 186, -4 }, - { 186, -2 }, - { 175, -1 }, - { 175, -1 }, - { 175, 0 }, - { 202, 0 }, - { 202, -3 }, - { 203, 0 }, - { 203, -2 }, - { 205, 0 }, - { 205, -2 }, - { 205, -4 }, - { 205, -4 }, - { 149, -6 }, - { 201, 0 }, - { 201, -2 }, - { 149, -8 }, - { 218, -5 }, - { 218, -7 }, - { 218, -3 }, - { 218, -5 }, - { 149, -6 }, - { 149, -7 }, - { 219, -2 }, - { 219, -1 }, - { 220, 0 }, - { 220, -3 }, - { 217, -3 }, - { 217, -1 }, - { 173, -3 }, - { 173, -1 }, - { 173, -1 }, - { 173, -3 }, - { 173, -5 }, - { 172, -1 }, - { 172, -1 }, - { 172, -1 }, - { 173, -1 }, - { 173, -3 }, - { 173, -6 }, - { 173, -5 }, - { 173, -4 }, - { 172, -1 }, - { 173, -5 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 173, -3 }, - { 221, -2 }, - { 173, -3 }, - { 173, -5 }, - { 173, -2 }, - { 173, -3 }, - { 173, -3 }, - { 173, -4 }, - { 173, -2 }, - { 173, -2 }, - { 173, -2 }, - { 173, -2 }, - { 222, -1 }, - { 222, -2 }, - { 173, -5 }, - { 223, -1 }, - { 223, -2 }, - { 173, -5 }, - { 173, -3 }, - { 173, -5 }, - { 173, -5 }, - { 173, -4 }, - { 173, -5 }, - { 226, -5 }, - { 226, -4 }, - { 227, -2 }, - { 227, 0 }, - { 225, -1 }, - { 225, 0 }, - { 208, 0 }, - { 207, -3 }, - { 207, -1 }, - { 224, 0 }, - { 224, -3 }, - { 149, -12 }, - { 228, -1 }, - { 228, 0 }, - { 177, 0 }, - { 177, -3 }, - { 187, -5 }, - { 187, -3 }, - { 229, 0 }, - { 229, -2 }, - { 149, -4 }, - { 149, -1 }, - { 149, -2 }, - { 149, -3 }, - { 149, -5 }, - { 149, -6 }, - { 149, -5 }, - { 149, -6 }, - { 169, -2 }, - { 170, -2 }, - { 149, -5 }, - { 231, -11 }, - { 233, -1 }, - { 233, -2 }, - { 233, 0 }, - { 234, -1 }, - { 234, -1 }, - { 234, -3 }, - { 236, 0 }, - { 236, -2 }, - { 232, -3 }, - { 232, -2 }, - { 238, -3 }, - { 239, -3 }, - { 239, -2 }, - { 237, -7 }, - { 237, -5 }, - { 237, -5 }, - { 237, -1 }, - { 173, -4 }, - { 173, -6 }, - { 191, -1 }, - { 191, -1 }, - { 191, -1 }, - { 149, -4 }, - { 149, -6 }, - { 149, -3 }, - { 241, 0 }, - { 241, -2 }, - { 149, -1 }, - { 149, -3 }, - { 149, -1 }, - { 149, -3 }, - { 149, -6 }, - { 149, -7 }, - { 242, -1 }, - { 149, -1 }, - { 149, -4 }, - { 244, -8 }, - { 246, 0 }, - { 247, -1 }, - { 247, -3 }, - { 248, -1 }, - { 196, 0 }, - { 196, -2 }, - { 196, -3 }, - { 250, -6 }, - { 250, -8 }, - { 144, -1 }, - { 145, -2 }, - { 145, -1 }, - { 146, -1 }, - { 146, -3 }, - { 147, 0 }, - { 151, 0 }, - { 151, -1 }, - { 151, -2 }, - { 153, -1 }, - { 153, 0 }, - { 149, -2 }, - { 160, -4 }, - { 160, -2 }, - { 152, -1 }, - { 152, -1 }, - { 152, -1 }, - { 166, -1 }, - { 167, -1 }, - { 168, -1 }, - { 168, -1 }, - { 165, -2 }, - { 165, 0 }, - { 171, -2 }, - { 161, -2 }, - { 183, -3 }, - { 183, -1 }, - { 184, 0 }, - { 188, -1 }, - { 190, -1 }, - { 194, -1 }, - { 195, -1 }, - { 209, -2 }, - { 210, -1 }, - { 173, -1 }, - { 221, -1 }, - { 208, -1 }, - { 230, -1 }, - { 230, -1 }, - { 230, -1 }, - { 230, -1 }, - { 230, -1 }, - { 169, -1 }, - { 235, 0 }, - { 235, -3 }, - { 238, -1 }, - { 239, 0 }, - { 240, -1 }, - { 240, 0 }, - { 243, 0 }, - { 243, -1 }, - { 245, -1 }, - { 245, -3 }, - { 246, -2 }, - { 249, 0 }, - { 249, -4 }, - { 249, -2 }, + { 149, -1 }, /* (0) explain ::= EXPLAIN */ + { 149, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */ + { 148, -1 }, /* (2) cmdx ::= cmd */ + { 150, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */ + { 151, 0 }, /* (4) transtype ::= */ + { 151, -1 }, /* (5) transtype ::= DEFERRED */ + { 151, -1 }, /* (6) transtype ::= IMMEDIATE */ + { 151, -1 }, /* (7) transtype ::= EXCLUSIVE */ + { 150, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */ + { 150, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */ + { 150, -2 }, /* (10) cmd ::= SAVEPOINT nm */ + { 150, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */ + { 150, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + { 155, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + { 157, -1 }, /* (14) createkw ::= CREATE */ + { 159, 0 }, /* (15) ifnotexists ::= */ + { 159, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */ + { 158, -1 }, /* (17) temp ::= TEMP */ + { 158, 0 }, /* (18) temp ::= */ + { 156, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ + { 156, -2 }, /* (20) create_table_args ::= AS select */ + { 163, 0 }, /* (21) table_options ::= */ + { 163, -2 }, /* (22) table_options ::= WITHOUT nm */ + { 165, -2 }, /* (23) columnname ::= nm typetoken */ + { 167, 0 }, /* (24) typetoken ::= */ + { 167, -4 }, /* (25) typetoken ::= typename LP signed RP */ + { 167, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */ + { 168, -2 }, /* (27) typename ::= typename ID|STRING */ + { 172, 0 }, /* (28) scanpt ::= */ + { 173, -2 }, /* (29) ccons ::= CONSTRAINT nm */ + { 173, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */ + { 173, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */ + { 173, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */ + { 173, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */ + { 173, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ + { 173, -3 }, /* (35) ccons ::= NOT NULL onconf */ + { 173, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + { 173, -2 }, /* (37) ccons ::= UNIQUE onconf */ + { 173, -4 }, /* (38) ccons ::= CHECK LP expr RP */ + { 173, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ + { 173, -1 }, /* (40) ccons ::= defer_subclause */ + { 173, -2 }, /* (41) ccons ::= COLLATE ID|STRING */ + { 178, 0 }, /* (42) autoinc ::= */ + { 178, -1 }, /* (43) autoinc ::= AUTOINCR */ + { 180, 0 }, /* (44) refargs ::= */ + { 180, -2 }, /* (45) refargs ::= refargs refarg */ + { 182, -2 }, /* (46) refarg ::= MATCH nm */ + { 182, -3 }, /* (47) refarg ::= ON INSERT refact */ + { 182, -3 }, /* (48) refarg ::= ON DELETE refact */ + { 182, -3 }, /* (49) refarg ::= ON UPDATE refact */ + { 183, -2 }, /* (50) refact ::= SET NULL */ + { 183, -2 }, /* (51) refact ::= SET DEFAULT */ + { 183, -1 }, /* (52) refact ::= CASCADE */ + { 183, -1 }, /* (53) refact ::= RESTRICT */ + { 183, -2 }, /* (54) refact ::= NO ACTION */ + { 181, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + { 181, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + { 184, 0 }, /* (57) init_deferred_pred_opt ::= */ + { 184, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + { 184, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + { 162, 0 }, /* (60) conslist_opt ::= */ + { 186, -1 }, /* (61) tconscomma ::= COMMA */ + { 187, -2 }, /* (62) tcons ::= CONSTRAINT nm */ + { 187, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + { 187, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ + { 187, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */ + { 187, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + { 190, 0 }, /* (67) defer_subclause_opt ::= */ + { 176, 0 }, /* (68) onconf ::= */ + { 176, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */ + { 191, 0 }, /* (70) orconf ::= */ + { 191, -2 }, /* (71) orconf ::= OR resolvetype */ + { 192, -1 }, /* (72) resolvetype ::= IGNORE */ + { 192, -1 }, /* (73) resolvetype ::= REPLACE */ + { 150, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */ + { 194, -2 }, /* (75) ifexists ::= IF EXISTS */ + { 194, 0 }, /* (76) ifexists ::= */ + { 150, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + { 150, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */ + { 150, -1 }, /* (79) cmd ::= select */ + { 164, -3 }, /* (80) select ::= WITH wqlist selectnowith */ + { 164, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ + { 164, -1 }, /* (82) select ::= selectnowith */ + { 196, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ + { 199, -1 }, /* (84) multiselect_op ::= UNION */ + { 199, -2 }, /* (85) multiselect_op ::= UNION ALL */ + { 199, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ + { 197, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + { 208, -4 }, /* (88) values ::= VALUES LP nexprlist RP */ + { 208, -5 }, /* (89) values ::= values COMMA LP exprlist RP */ + { 200, -1 }, /* (90) distinct ::= DISTINCT */ + { 200, -1 }, /* (91) distinct ::= ALL */ + { 200, 0 }, /* (92) distinct ::= */ + { 211, 0 }, /* (93) sclp ::= */ + { 201, -5 }, /* (94) selcollist ::= sclp scanpt expr scanpt as */ + { 201, -3 }, /* (95) selcollist ::= sclp scanpt STAR */ + { 201, -5 }, /* (96) selcollist ::= sclp scanpt nm DOT STAR */ + { 212, -2 }, /* (97) as ::= AS nm */ + { 212, 0 }, /* (98) as ::= */ + { 202, 0 }, /* (99) from ::= */ + { 202, -2 }, /* (100) from ::= FROM seltablist */ + { 214, -2 }, /* (101) stl_prefix ::= seltablist joinop */ + { 214, 0 }, /* (102) stl_prefix ::= */ + { 213, -7 }, /* (103) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + { 213, -9 }, /* (104) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + { 213, -7 }, /* (105) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + { 213, -7 }, /* (106) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + { 160, 0 }, /* (107) dbnm ::= */ + { 160, -2 }, /* (108) dbnm ::= DOT nm */ + { 195, -1 }, /* (109) fullname ::= nm */ + { 195, -3 }, /* (110) fullname ::= nm DOT nm */ + { 219, -1 }, /* (111) xfullname ::= nm */ + { 219, -3 }, /* (112) xfullname ::= nm DOT nm */ + { 219, -5 }, /* (113) xfullname ::= nm DOT nm AS nm */ + { 219, -3 }, /* (114) xfullname ::= nm AS nm */ + { 215, -1 }, /* (115) joinop ::= COMMA|JOIN */ + { 215, -2 }, /* (116) joinop ::= JOIN_KW JOIN */ + { 215, -3 }, /* (117) joinop ::= JOIN_KW nm JOIN */ + { 215, -4 }, /* (118) joinop ::= JOIN_KW nm nm JOIN */ + { 217, -2 }, /* (119) on_opt ::= ON expr */ + { 217, 0 }, /* (120) on_opt ::= */ + { 216, 0 }, /* (121) indexed_opt ::= */ + { 216, -3 }, /* (122) indexed_opt ::= INDEXED BY nm */ + { 216, -2 }, /* (123) indexed_opt ::= NOT INDEXED */ + { 218, -4 }, /* (124) using_opt ::= USING LP idlist RP */ + { 218, 0 }, /* (125) using_opt ::= */ + { 206, 0 }, /* (126) orderby_opt ::= */ + { 206, -3 }, /* (127) orderby_opt ::= ORDER BY sortlist */ + { 188, -4 }, /* (128) sortlist ::= sortlist COMMA expr sortorder */ + { 188, -2 }, /* (129) sortlist ::= expr sortorder */ + { 177, -1 }, /* (130) sortorder ::= ASC */ + { 177, -1 }, /* (131) sortorder ::= DESC */ + { 177, 0 }, /* (132) sortorder ::= */ + { 204, 0 }, /* (133) groupby_opt ::= */ + { 204, -3 }, /* (134) groupby_opt ::= GROUP BY nexprlist */ + { 205, 0 }, /* (135) having_opt ::= */ + { 205, -2 }, /* (136) having_opt ::= HAVING expr */ + { 207, 0 }, /* (137) limit_opt ::= */ + { 207, -2 }, /* (138) limit_opt ::= LIMIT expr */ + { 207, -4 }, /* (139) limit_opt ::= LIMIT expr OFFSET expr */ + { 207, -4 }, /* (140) limit_opt ::= LIMIT expr COMMA expr */ + { 150, -6 }, /* (141) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ + { 203, 0 }, /* (142) where_opt ::= */ + { 203, -2 }, /* (143) where_opt ::= WHERE expr */ + { 150, -8 }, /* (144) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ + { 222, -5 }, /* (145) setlist ::= setlist COMMA nm EQ expr */ + { 222, -7 }, /* (146) setlist ::= setlist COMMA LP idlist RP EQ expr */ + { 222, -3 }, /* (147) setlist ::= nm EQ expr */ + { 222, -5 }, /* (148) setlist ::= LP idlist RP EQ expr */ + { 150, -7 }, /* (149) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + { 150, -7 }, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ + { 225, 0 }, /* (151) upsert ::= */ + { 225, -11 }, /* (152) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ + { 225, -8 }, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ + { 225, -4 }, /* (154) upsert ::= ON CONFLICT DO NOTHING */ + { 223, -2 }, /* (155) insert_cmd ::= INSERT orconf */ + { 223, -1 }, /* (156) insert_cmd ::= REPLACE */ + { 224, 0 }, /* (157) idlist_opt ::= */ + { 224, -3 }, /* (158) idlist_opt ::= LP idlist RP */ + { 220, -3 }, /* (159) idlist ::= idlist COMMA nm */ + { 220, -1 }, /* (160) idlist ::= nm */ + { 175, -3 }, /* (161) expr ::= LP expr RP */ + { 175, -1 }, /* (162) expr ::= ID|INDEXED */ + { 175, -1 }, /* (163) expr ::= JOIN_KW */ + { 175, -3 }, /* (164) expr ::= nm DOT nm */ + { 175, -5 }, /* (165) expr ::= nm DOT nm DOT nm */ + { 174, -1 }, /* (166) term ::= NULL|FLOAT|BLOB */ + { 174, -1 }, /* (167) term ::= STRING */ + { 174, -1 }, /* (168) term ::= INTEGER */ + { 175, -1 }, /* (169) expr ::= VARIABLE */ + { 175, -3 }, /* (170) expr ::= expr COLLATE ID|STRING */ + { 175, -6 }, /* (171) expr ::= CAST LP expr AS typetoken RP */ + { 175, -5 }, /* (172) expr ::= ID|INDEXED LP distinct exprlist RP */ + { 175, -4 }, /* (173) expr ::= ID|INDEXED LP STAR RP */ + { 174, -1 }, /* (174) term ::= CTIME_KW */ + { 175, -5 }, /* (175) expr ::= LP nexprlist COMMA expr RP */ + { 175, -3 }, /* (176) expr ::= expr AND expr */ + { 175, -3 }, /* (177) expr ::= expr OR expr */ + { 175, -3 }, /* (178) expr ::= expr LT|GT|GE|LE expr */ + { 175, -3 }, /* (179) expr ::= expr EQ|NE expr */ + { 175, -3 }, /* (180) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + { 175, -3 }, /* (181) expr ::= expr PLUS|MINUS expr */ + { 175, -3 }, /* (182) expr ::= expr STAR|SLASH|REM expr */ + { 175, -3 }, /* (183) expr ::= expr CONCAT expr */ + { 226, -2 }, /* (184) likeop ::= NOT LIKE_KW|MATCH */ + { 175, -3 }, /* (185) expr ::= expr likeop expr */ + { 175, -5 }, /* (186) expr ::= expr likeop expr ESCAPE expr */ + { 175, -2 }, /* (187) expr ::= expr ISNULL|NOTNULL */ + { 175, -3 }, /* (188) expr ::= expr NOT NULL */ + { 175, -3 }, /* (189) expr ::= expr IS expr */ + { 175, -4 }, /* (190) expr ::= expr IS NOT expr */ + { 175, -2 }, /* (191) expr ::= NOT expr */ + { 175, -2 }, /* (192) expr ::= BITNOT expr */ + { 175, -2 }, /* (193) expr ::= MINUS expr */ + { 175, -2 }, /* (194) expr ::= PLUS expr */ + { 227, -1 }, /* (195) between_op ::= BETWEEN */ + { 227, -2 }, /* (196) between_op ::= NOT BETWEEN */ + { 175, -5 }, /* (197) expr ::= expr between_op expr AND expr */ + { 228, -1 }, /* (198) in_op ::= IN */ + { 228, -2 }, /* (199) in_op ::= NOT IN */ + { 175, -5 }, /* (200) expr ::= expr in_op LP exprlist RP */ + { 175, -3 }, /* (201) expr ::= LP select RP */ + { 175, -5 }, /* (202) expr ::= expr in_op LP select RP */ + { 175, -5 }, /* (203) expr ::= expr in_op nm dbnm paren_exprlist */ + { 175, -4 }, /* (204) expr ::= EXISTS LP select RP */ + { 175, -5 }, /* (205) expr ::= CASE case_operand case_exprlist case_else END */ + { 231, -5 }, /* (206) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + { 231, -4 }, /* (207) case_exprlist ::= WHEN expr THEN expr */ + { 232, -2 }, /* (208) case_else ::= ELSE expr */ + { 232, 0 }, /* (209) case_else ::= */ + { 230, -1 }, /* (210) case_operand ::= expr */ + { 230, 0 }, /* (211) case_operand ::= */ + { 210, 0 }, /* (212) exprlist ::= */ + { 209, -3 }, /* (213) nexprlist ::= nexprlist COMMA expr */ + { 209, -1 }, /* (214) nexprlist ::= expr */ + { 229, 0 }, /* (215) paren_exprlist ::= */ + { 229, -3 }, /* (216) paren_exprlist ::= LP exprlist RP */ + { 150, -12 }, /* (217) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + { 233, -1 }, /* (218) uniqueflag ::= UNIQUE */ + { 233, 0 }, /* (219) uniqueflag ::= */ + { 179, 0 }, /* (220) eidlist_opt ::= */ + { 179, -3 }, /* (221) eidlist_opt ::= LP eidlist RP */ + { 189, -5 }, /* (222) eidlist ::= eidlist COMMA nm collate sortorder */ + { 189, -3 }, /* (223) eidlist ::= nm collate sortorder */ + { 234, 0 }, /* (224) collate ::= */ + { 234, -2 }, /* (225) collate ::= COLLATE ID|STRING */ + { 150, -4 }, /* (226) cmd ::= DROP INDEX ifexists fullname */ + { 150, -1 }, /* (227) cmd ::= VACUUM */ + { 150, -2 }, /* (228) cmd ::= VACUUM nm */ + { 150, -3 }, /* (229) cmd ::= PRAGMA nm dbnm */ + { 150, -5 }, /* (230) cmd ::= PRAGMA nm dbnm EQ nmnum */ + { 150, -6 }, /* (231) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + { 150, -5 }, /* (232) cmd ::= PRAGMA nm dbnm EQ minus_num */ + { 150, -6 }, /* (233) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + { 170, -2 }, /* (234) plus_num ::= PLUS INTEGER|FLOAT */ + { 171, -2 }, /* (235) minus_num ::= MINUS INTEGER|FLOAT */ + { 150, -5 }, /* (236) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + { 236, -11 }, /* (237) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + { 238, -1 }, /* (238) trigger_time ::= BEFORE|AFTER */ + { 238, -2 }, /* (239) trigger_time ::= INSTEAD OF */ + { 238, 0 }, /* (240) trigger_time ::= */ + { 239, -1 }, /* (241) trigger_event ::= DELETE|INSERT */ + { 239, -1 }, /* (242) trigger_event ::= UPDATE */ + { 239, -3 }, /* (243) trigger_event ::= UPDATE OF idlist */ + { 241, 0 }, /* (244) when_clause ::= */ + { 241, -2 }, /* (245) when_clause ::= WHEN expr */ + { 237, -3 }, /* (246) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + { 237, -2 }, /* (247) trigger_cmd_list ::= trigger_cmd SEMI */ + { 243, -3 }, /* (248) trnm ::= nm DOT nm */ + { 244, -3 }, /* (249) tridxby ::= INDEXED BY nm */ + { 244, -2 }, /* (250) tridxby ::= NOT INDEXED */ + { 242, -8 }, /* (251) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ + { 242, -8 }, /* (252) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + { 242, -6 }, /* (253) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + { 242, -3 }, /* (254) trigger_cmd ::= scanpt select scanpt */ + { 175, -4 }, /* (255) expr ::= RAISE LP IGNORE RP */ + { 175, -6 }, /* (256) expr ::= RAISE LP raisetype COMMA nm RP */ + { 193, -1 }, /* (257) raisetype ::= ROLLBACK */ + { 193, -1 }, /* (258) raisetype ::= ABORT */ + { 193, -1 }, /* (259) raisetype ::= FAIL */ + { 150, -4 }, /* (260) cmd ::= DROP TRIGGER ifexists fullname */ + { 150, -6 }, /* (261) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + { 150, -3 }, /* (262) cmd ::= DETACH database_kw_opt expr */ + { 246, 0 }, /* (263) key_opt ::= */ + { 246, -2 }, /* (264) key_opt ::= KEY expr */ + { 150, -1 }, /* (265) cmd ::= REINDEX */ + { 150, -3 }, /* (266) cmd ::= REINDEX nm dbnm */ + { 150, -1 }, /* (267) cmd ::= ANALYZE */ + { 150, -3 }, /* (268) cmd ::= ANALYZE nm dbnm */ + { 150, -6 }, /* (269) cmd ::= ALTER TABLE fullname RENAME TO nm */ + { 150, -7 }, /* (270) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + { 247, -1 }, /* (271) add_column_fullname ::= fullname */ + { 150, -1 }, /* (272) cmd ::= create_vtab */ + { 150, -4 }, /* (273) cmd ::= create_vtab LP vtabarglist RP */ + { 249, -8 }, /* (274) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + { 251, 0 }, /* (275) vtabarg ::= */ + { 252, -1 }, /* (276) vtabargtoken ::= ANY */ + { 252, -3 }, /* (277) vtabargtoken ::= lp anylist RP */ + { 253, -1 }, /* (278) lp ::= LP */ + { 221, -2 }, /* (279) with ::= WITH wqlist */ + { 221, -3 }, /* (280) with ::= WITH RECURSIVE wqlist */ + { 198, -6 }, /* (281) wqlist ::= nm eidlist_opt AS LP select RP */ + { 198, -8 }, /* (282) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + { 145, -1 }, /* (283) input ::= cmdlist */ + { 146, -2 }, /* (284) cmdlist ::= cmdlist ecmd */ + { 146, -1 }, /* (285) cmdlist ::= ecmd */ + { 147, -1 }, /* (286) ecmd ::= SEMI */ + { 147, -2 }, /* (287) ecmd ::= cmdx SEMI */ + { 147, -2 }, /* (288) ecmd ::= explain cmdx */ + { 152, 0 }, /* (289) trans_opt ::= */ + { 152, -1 }, /* (290) trans_opt ::= TRANSACTION */ + { 152, -2 }, /* (291) trans_opt ::= TRANSACTION nm */ + { 154, -1 }, /* (292) savepoint_opt ::= SAVEPOINT */ + { 154, 0 }, /* (293) savepoint_opt ::= */ + { 150, -2 }, /* (294) cmd ::= create_table create_table_args */ + { 161, -4 }, /* (295) columnlist ::= columnlist COMMA columnname carglist */ + { 161, -2 }, /* (296) columnlist ::= columnname carglist */ + { 153, -1 }, /* (297) nm ::= ID|INDEXED */ + { 153, -1 }, /* (298) nm ::= STRING */ + { 153, -1 }, /* (299) nm ::= JOIN_KW */ + { 167, -1 }, /* (300) typetoken ::= typename */ + { 168, -1 }, /* (301) typename ::= ID|STRING */ + { 169, -1 }, /* (302) signed ::= plus_num */ + { 169, -1 }, /* (303) signed ::= minus_num */ + { 166, -2 }, /* (304) carglist ::= carglist ccons */ + { 166, 0 }, /* (305) carglist ::= */ + { 173, -2 }, /* (306) ccons ::= NULL onconf */ + { 162, -2 }, /* (307) conslist_opt ::= COMMA conslist */ + { 185, -3 }, /* (308) conslist ::= conslist tconscomma tcons */ + { 185, -1 }, /* (309) conslist ::= tcons */ + { 186, 0 }, /* (310) tconscomma ::= */ + { 190, -1 }, /* (311) defer_subclause_opt ::= defer_subclause */ + { 192, -1 }, /* (312) resolvetype ::= raisetype */ + { 196, -1 }, /* (313) selectnowith ::= oneselect */ + { 197, -1 }, /* (314) oneselect ::= values */ + { 211, -2 }, /* (315) sclp ::= selcollist COMMA */ + { 212, -1 }, /* (316) as ::= ID|STRING */ + { 175, -1 }, /* (317) expr ::= term */ + { 226, -1 }, /* (318) likeop ::= LIKE_KW|MATCH */ + { 210, -1 }, /* (319) exprlist ::= nexprlist */ + { 235, -1 }, /* (320) nmnum ::= plus_num */ + { 235, -1 }, /* (321) nmnum ::= nm */ + { 235, -1 }, /* (322) nmnum ::= ON */ + { 235, -1 }, /* (323) nmnum ::= DELETE */ + { 235, -1 }, /* (324) nmnum ::= DEFAULT */ + { 170, -1 }, /* (325) plus_num ::= INTEGER|FLOAT */ + { 240, 0 }, /* (326) foreach_clause ::= */ + { 240, -3 }, /* (327) foreach_clause ::= FOR EACH ROW */ + { 243, -1 }, /* (328) trnm ::= nm */ + { 244, 0 }, /* (329) tridxby ::= */ + { 245, -1 }, /* (330) database_kw_opt ::= DATABASE */ + { 245, 0 }, /* (331) database_kw_opt ::= */ + { 248, 0 }, /* (332) kwcolumn_opt ::= */ + { 248, -1 }, /* (333) kwcolumn_opt ::= COLUMNKW */ + { 250, -1 }, /* (334) vtabarglist ::= vtabarg */ + { 250, -3 }, /* (335) vtabarglist ::= vtabarglist COMMA vtabarg */ + { 251, -2 }, /* (336) vtabarg ::= vtabarg vtabargtoken */ + { 254, 0 }, /* (337) anylist ::= */ + { 254, -4 }, /* (338) anylist ::= anylist LP anylist RP */ + { 254, -2 }, /* (339) anylist ::= anylist ANY */ + { 221, 0 }, /* (340) with ::= */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -139132,22 +143848,39 @@ static void yy_accept(yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. +** +** The yyLookahead and yyLookaheadToken parameters provide reduce actions +** access to the lookahead token (if any). The yyLookahead will be YYNOCODE +** if the lookahead token has already been consumed. As this procedure is +** only called from one place, optimizing compilers will in-line it, which +** means that the extra parameters have no performance impact. */ -static void yy_reduce( +static YYACTIONTYPE yy_reduce( yyParser *yypParser, /* The parser */ - unsigned int yyruleno /* Number of the rule by which to reduce */ + unsigned int yyruleno, /* Number of the rule by which to reduce */ + int yyLookahead, /* Lookahead token, or YYNOCODE if none */ + sqlite3ParserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ + sqlite3ParserCTX_PDECL /* %extra_context */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ - sqlite3ParserARG_FETCH; + sqlite3ParserARG_FETCH + (void)yyLookahead; + (void)yyLookaheadToken; yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[yysize].stateno); + if( yysize ){ + fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + yyTracePrompt, + yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); + }else{ + fprintf(yyTraceFILE, "%sReduce %d [%s].\n", + yyTracePrompt, yyruleno, yyRuleName[yyruleno]); + } } #endif /* NDEBUG */ @@ -139164,13 +143897,19 @@ static void yy_reduce( #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } yymsp = yypParser->yytos; } @@ -139198,15 +143937,15 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy194);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy194 = TK_DEFERRED;} +{yymsp[1].minor.yy502 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); -{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/} +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -139229,7 +143968,7 @@ static void yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); } break; case 14: /* createkw ::= CREATE */ @@ -139238,38 +143977,38 @@ static void yy_reduce( case 15: /* ifnotexists ::= */ case 18: /* temp ::= */ yytestcase(yyruleno==18); case 21: /* table_options ::= */ yytestcase(yyruleno==21); - case 41: /* autoinc ::= */ yytestcase(yyruleno==41); - case 56: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==56); - case 66: /* defer_subclause_opt ::= */ yytestcase(yyruleno==66); - case 75: /* ifexists ::= */ yytestcase(yyruleno==75); - case 89: /* distinct ::= */ yytestcase(yyruleno==89); - case 212: /* collate ::= */ yytestcase(yyruleno==212); -{yymsp[1].minor.yy194 = 0;} + case 42: /* autoinc ::= */ yytestcase(yyruleno==42); + case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); + case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); + case 76: /* ifexists ::= */ yytestcase(yyruleno==76); + case 92: /* distinct ::= */ yytestcase(yyruleno==92); + case 224: /* collate ::= */ yytestcase(yyruleno==224); +{yymsp[1].minor.yy502 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy194 = 1;} +{yymsp[-2].minor.yy502 = 1;} break; case 17: /* temp ::= TEMP */ - case 42: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==42); -{yymsp[0].minor.yy194 = 1;} + case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); +{yymsp[0].minor.yy502 = 1;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy502,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy399); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399); } break; case 22: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy502 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy194 = 0; + yymsp[-1].minor.yy502 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -139278,8 +144017,8 @@ static void yy_reduce( {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; case 24: /* typetoken ::= */ - case 59: /* conslist_opt ::= */ yytestcase(yyruleno==59); - case 95: /* as ::= */ yytestcase(yyruleno==95); + case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60); + case 98: /* as ::= */ yytestcase(yyruleno==98); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; case 25: /* typetoken ::= typename LP signed RP */ @@ -139295,210 +144034,239 @@ static void yy_reduce( case 27: /* typename ::= typename ID|STRING */ {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} break; - case 28: /* ccons ::= CONSTRAINT nm */ - case 61: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==61); + case 28: /* scanpt ::= */ +{ + assert( yyLookahead!=YYNOCODE ); + yymsp[1].minor.yy36 = yyLookaheadToken.z; +} + break; + case 29: /* ccons ::= CONSTRAINT nm */ + case 62: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==62); {pParse->constraintName = yymsp[0].minor.yy0;} break; - case 29: /* ccons ::= DEFAULT term */ - case 31: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==31); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);} + case 30: /* ccons ::= DEFAULT scanpt term scanpt */ +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy36,yymsp[0].minor.yy36);} break; - case 30: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} + case 31: /* ccons ::= DEFAULT LP expr RP */ +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; - case 32: /* ccons ::= DEFAULT MINUS term */ + case 32: /* ccons ::= DEFAULT PLUS term scanpt */ +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36);} + break; + case 33: /* ccons ::= DEFAULT MINUS term scanpt */ { - ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); - v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy190.zEnd; - sqlite3AddDefaultValue(pParse,&v); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy182, 0); + sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36); } break; - case 33: /* ccons ::= DEFAULT ID|INDEXED */ + case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */ { - ExprSpan v; - spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0); - sqlite3AddDefaultValue(pParse,&v); + Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); + if( p ){ + sqlite3ExprIdToTrueFalse(p); + testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); + } + sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); } break; - case 34: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} + case 35: /* ccons ::= NOT NULL onconf */ +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);} break; - case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} + case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);} break; - case 36: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0, + case 37: /* ccons ::= UNIQUE onconf */ +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 37: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);} + case 38: /* ccons ::= CHECK LP expr RP */ +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy182);} break; - case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} + case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy232,yymsp[0].minor.yy502);} break; - case 39: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} + case 40: /* ccons ::= defer_subclause */ +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);} break; - case 40: /* ccons ::= COLLATE ID|STRING */ + case 41: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 43: /* refargs ::= */ -{ yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */} + case 44: /* refargs ::= */ +{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */} break; - case 44: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } + case 45: /* refargs ::= refargs refarg */ +{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; } break; - case 45: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; } + case 46: /* refarg ::= MATCH nm */ +{ yymsp[-1].minor.yy107.value = 0; yymsp[-1].minor.yy107.mask = 0x000000; } break; - case 46: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; } + case 47: /* refarg ::= ON INSERT refact */ +{ yymsp[-2].minor.yy107.value = 0; yymsp[-2].minor.yy107.mask = 0x000000; } break; - case 47: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; } + case 48: /* refarg ::= ON DELETE refact */ +{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy107.mask = 0x0000ff; } break; - case 48: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; } + case 49: /* refarg ::= ON UPDATE refact */ +{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy107.mask = 0x00ff00; } break; - case 49: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */} + case 50: /* refact ::= SET NULL */ +{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */} break; - case 50: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */} + case 51: /* refact ::= SET DEFAULT */ +{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */} break; - case 51: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */} + case 52: /* refact ::= CASCADE */ +{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */} break; - case 52: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */} + case 53: /* refact ::= RESTRICT */ +{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */} break; - case 53: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */} + case 54: /* refact ::= NO ACTION */ +{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */} break; - case 54: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy194 = 0;} + case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +{yymsp[-2].minor.yy502 = 0;} break; - case 55: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 70: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==70); - case 143: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==143); -{yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} + case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); + case 155: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==155); +{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;} break; - case 57: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 74: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==74); - case 184: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==184); - case 187: /* in_op ::= NOT IN */ yytestcase(yyruleno==187); - case 213: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==213); -{yymsp[-1].minor.yy194 = 1;} + case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ + case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); + case 196: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==196); + case 199: /* in_op ::= NOT IN */ yytestcase(yyruleno==199); + case 225: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==225); +{yymsp[-1].minor.yy502 = 1;} break; - case 58: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy194 = 0;} + case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +{yymsp[-1].minor.yy502 = 0;} break; - case 60: /* tconscomma ::= COMMA */ + case 61: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 62: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} + case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy232,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} break; - case 63: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0, + case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy232,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 64: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);} + case 65: /* tcons ::= CHECK LP expr RP onconf */ +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy182);} break; - case 65: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy232, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy502); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502); } break; - case 67: /* onconf ::= */ - case 69: /* orconf ::= */ yytestcase(yyruleno==69); -{yymsp[1].minor.yy194 = OE_Default;} + case 68: /* onconf ::= */ + case 70: /* orconf ::= */ yytestcase(yyruleno==70); +{yymsp[1].minor.yy502 = OE_Default;} break; - case 68: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;} + case 69: /* onconf ::= ON CONFLICT resolvetype */ +{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;} break; - case 71: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy194 = OE_Ignore;} + case 72: /* resolvetype ::= IGNORE */ +{yymsp[0].minor.yy502 = OE_Ignore;} break; - case 72: /* resolvetype ::= REPLACE */ - case 144: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==144); -{yymsp[0].minor.yy194 = OE_Replace;} + case 73: /* resolvetype ::= REPLACE */ + case 156: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==156); +{yymsp[0].minor.yy502 = OE_Replace;} break; - case 73: /* cmd ::= DROP TABLE ifexists fullname */ + case 74: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194); + sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0, yymsp[-1].minor.yy502); } break; - case 76: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[0].minor.yy243, yymsp[-7].minor.yy194, yymsp[-5].minor.yy194); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[0].minor.yy399, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502); } break; - case 77: /* cmd ::= DROP VIEW ifexists fullname */ + case 78: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); + sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1, yymsp[-1].minor.yy502); } break; - case 78: /* cmd ::= select */ + case 79: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); + sqlite3Select(pParse, yymsp[0].minor.yy399, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399); } break; - case 79: /* select ::= with selectnowith */ + case 80: /* select ::= WITH wqlist selectnowith */ { - Select *p = yymsp[0].minor.yy243; + Select *p = yymsp[0].minor.yy399; if( p ){ - p->pWith = yymsp[-1].minor.yy285; + p->pWith = yymsp[-1].minor.yy91; parserDoubleLinkSelect(pParse, p); }else{ - sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy285); + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91); } - yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/ + yymsp[-2].minor.yy399 = p; } break; - case 80: /* selectnowith ::= selectnowith multiselect_op oneselect */ + case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */ { - Select *pRhs = yymsp[0].minor.yy243; - Select *pLhs = yymsp[-2].minor.yy243; + Select *p = yymsp[0].minor.yy399; + if( p ){ + p->pWith = yymsp[-1].minor.yy91; + parserDoubleLinkSelect(pParse, p); + }else{ + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91); + } + yymsp[-3].minor.yy399 = p; +} + break; + case 82: /* select ::= selectnowith */ +{ + Select *p = yymsp[0].minor.yy399; + if( p ){ + parserDoubleLinkSelect(pParse, p); + } + yymsp[0].minor.yy399 = p; /*A-overwrites-X*/ +} + break; + case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */ +{ + Select *pRhs = yymsp[0].minor.yy399; + Select *pLhs = yymsp[-2].minor.yy399; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); - pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy194; + pRhs->op = (u8)yymsp[-1].minor.yy502; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy194!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy243 = pRhs; + yymsp[-2].minor.yy399 = pRhs; } break; - case 81: /* multiselect_op ::= UNION */ - case 83: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==83); -{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/} + case 84: /* multiselect_op ::= UNION */ + case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86); +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/} break; - case 82: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy194 = TK_ALL;} + case 85: /* multiselect_op ::= UNION ALL */ +{yymsp[-1].minor.yy502 = TK_ALL;} break; - case 84: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { #if SELECTTRACE_ENABLED Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ #endif - yymsp[-8].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset); + yymsp[-8].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy232,yymsp[-5].minor.yy427,yymsp[-4].minor.yy182,yymsp[-3].minor.yy232,yymsp[-2].minor.yy182,yymsp[-1].minor.yy232,yymsp[-7].minor.yy502,yymsp[0].minor.yy182); #if SELECTTRACE_ENABLED /* Populate the Select.zSelName[] string that is used to help with ** query planner debugging, to differentiate between multiple Select @@ -139509,483 +144277,492 @@ static void yy_reduce( ** comment to be the zSelName value. Otherwise, the label is #N where ** is an integer that is incremented with each SELECT statement seen. */ - if( yymsp[-8].minor.yy243!=0 ){ + if( yymsp[-8].minor.yy399!=0 ){ const char *z = s.z+6; int i; - sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "#%d", - ++pParse->nSelect); + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy399->zSelName), yymsp[-8].minor.yy399->zSelName,"#%d",++pParse->nSelect); while( z[0]==' ' ) z++; if( z[0]=='/' && z[1]=='*' ){ z += 2; while( z[0]==' ' ) z++; for(i=0; sqlite3Isalnum(z[i]); i++){} - sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "%.*s", i, z); + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy399->zSelName), yymsp[-8].minor.yy399->zSelName, "%.*s", i, z); } } #endif /* SELECTRACE_ENABLED */ } break; - case 85: /* values ::= VALUES LP nexprlist RP */ + case 88: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values,0,0); + yymsp[-3].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values,0); } break; - case 86: /* values ::= values COMMA LP exprlist RP */ + case 89: /* values ::= values COMMA LP exprlist RP */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy243; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); + Select *pRight, *pLeft = yymsp[-4].minor.yy399; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; - yymsp[-4].minor.yy243 = pRight; + yymsp[-4].minor.yy399 = pRight; }else{ - yymsp[-4].minor.yy243 = pLeft; + yymsp[-4].minor.yy399 = pLeft; } } break; - case 87: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy194 = SF_Distinct;} + case 90: /* distinct ::= DISTINCT */ +{yymsp[0].minor.yy502 = SF_Distinct;} break; - case 88: /* distinct ::= ALL */ -{yymsp[0].minor.yy194 = SF_All;} + case 91: /* distinct ::= ALL */ +{yymsp[0].minor.yy502 = SF_All;} break; - case 90: /* sclp ::= */ - case 118: /* orderby_opt ::= */ yytestcase(yyruleno==118); - case 125: /* groupby_opt ::= */ yytestcase(yyruleno==125); - case 200: /* exprlist ::= */ yytestcase(yyruleno==200); - case 203: /* paren_exprlist ::= */ yytestcase(yyruleno==203); - case 208: /* eidlist_opt ::= */ yytestcase(yyruleno==208); -{yymsp[1].minor.yy148 = 0;} + case 93: /* sclp ::= */ + case 126: /* orderby_opt ::= */ yytestcase(yyruleno==126); + case 133: /* groupby_opt ::= */ yytestcase(yyruleno==133); + case 212: /* exprlist ::= */ yytestcase(yyruleno==212); + case 215: /* paren_exprlist ::= */ yytestcase(yyruleno==215); + case 220: /* eidlist_opt ::= */ yytestcase(yyruleno==220); +{yymsp[1].minor.yy232 = 0;} break; - case 91: /* selcollist ::= sclp expr as */ + case 94: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy148, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy148,&yymsp[-1].minor.yy190); + yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[-2].minor.yy182); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy232,yymsp[-3].minor.yy36,yymsp[-1].minor.yy36); } break; - case 92: /* selcollist ::= sclp STAR */ + case 95: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); + yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy232, p); } break; - case 93: /* selcollist ::= sclp nm DOT STAR */ + case 96: /* selcollist ::= sclp scanpt nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); + yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, pDot); } break; - case 94: /* as ::= AS nm */ - case 105: /* dbnm ::= DOT nm */ yytestcase(yyruleno==105); - case 222: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==222); - case 223: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==223); + case 97: /* as ::= AS nm */ + case 108: /* dbnm ::= DOT nm */ yytestcase(yyruleno==108); + case 234: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==234); + case 235: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==235); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 96: /* from ::= */ -{yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} + case 99: /* from ::= */ +{yymsp[1].minor.yy427 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy427));} break; - case 97: /* from ::= FROM seltablist */ + case 100: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy185 = yymsp[0].minor.yy185; - sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185); + yymsp[-1].minor.yy427 = yymsp[0].minor.yy427; + sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy427); } break; - case 98: /* stl_prefix ::= seltablist joinop */ + case 101: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy185 && yymsp[-1].minor.yy185->nSrc>0) ) yymsp[-1].minor.yy185->a[yymsp[-1].minor.yy185->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy194; + if( ALWAYS(yymsp[-1].minor.yy427 && yymsp[-1].minor.yy427->nSrc>0) ) yymsp[-1].minor.yy427->a[yymsp[-1].minor.yy427->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502; } break; - case 99: /* stl_prefix ::= */ -{yymsp[1].minor.yy185 = 0;} + case 102: /* stl_prefix ::= */ +{yymsp[1].minor.yy427 = 0;} break; - case 100: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + case 103: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); - sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy185, &yymsp[-2].minor.yy0); + yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510); + sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy427, &yymsp[-2].minor.yy0); } break; - case 101: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + case 104: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ { - yymsp[-8].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy185,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); - sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy185, yymsp[-4].minor.yy148); + yymsp[-8].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy427,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510); + sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy427, yymsp[-4].minor.yy232); } break; - case 102: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + case 105: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy399,yymsp[-1].minor.yy182,yymsp[0].minor.yy510); } break; - case 103: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 106: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){ - yymsp[-6].minor.yy185 = yymsp[-4].minor.yy185; - }else if( yymsp[-4].minor.yy185->nSrc==1 ){ - yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); - if( yymsp[-6].minor.yy185 ){ - struct SrcList_item *pNew = &yymsp[-6].minor.yy185->a[yymsp[-6].minor.yy185->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy185->a; + if( yymsp[-6].minor.yy427==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy182==0 && yymsp[0].minor.yy510==0 ){ + yymsp[-6].minor.yy427 = yymsp[-4].minor.yy427; + }else if( yymsp[-4].minor.yy427->nSrc==1 ){ + yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510); + if( yymsp[-6].minor.yy427 ){ + struct SrcList_item *pNew = &yymsp[-6].minor.yy427->a[yymsp[-6].minor.yy427->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy427->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy185); + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy427); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,SF_NestedFrom,0,0); - yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy427); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy427,0,0,0,0,SF_NestedFrom,0); + yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy182,yymsp[0].minor.yy510); } } break; - case 104: /* dbnm ::= */ - case 113: /* indexed_opt ::= */ yytestcase(yyruleno==113); + case 107: /* dbnm ::= */ + case 121: /* indexed_opt ::= */ yytestcase(yyruleno==121); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 106: /* fullname ::= nm dbnm */ -{yymsp[-1].minor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 109: /* fullname ::= nm */ + case 111: /* xfullname ::= nm */ yytestcase(yyruleno==111); +{yymsp[0].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 107: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy194 = JT_INNER; } + case 110: /* fullname ::= nm DOT nm */ + case 112: /* xfullname ::= nm DOT nm */ yytestcase(yyruleno==112); +{yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 108: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + case 113: /* xfullname ::= nm DOT nm AS nm */ +{ + yymsp[-4].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy427 ) yymsp[-4].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); +} break; - case 109: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} + case 114: /* xfullname ::= nm AS nm */ +{ + yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy427 ) yymsp[-2].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); +} break; - case 110: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + case 115: /* joinop ::= COMMA|JOIN */ +{ yymsp[0].minor.yy502 = JT_INNER; } break; - case 111: /* on_opt ::= ON expr */ - case 128: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==128); - case 135: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==135); - case 196: /* case_else ::= ELSE expr */ yytestcase(yyruleno==196); -{yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} + case 116: /* joinop ::= JOIN_KW JOIN */ +{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 112: /* on_opt ::= */ - case 127: /* having_opt ::= */ yytestcase(yyruleno==127); - case 134: /* where_opt ::= */ yytestcase(yyruleno==134); - case 197: /* case_else ::= */ yytestcase(yyruleno==197); - case 199: /* case_operand ::= */ yytestcase(yyruleno==199); -{yymsp[1].minor.yy72 = 0;} + case 117: /* joinop ::= JOIN_KW nm JOIN */ +{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 114: /* indexed_opt ::= INDEXED BY nm */ + case 118: /* joinop ::= JOIN_KW nm nm JOIN */ +{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + break; + case 119: /* on_opt ::= ON expr */ + case 136: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==136); + case 143: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==143); + case 208: /* case_else ::= ELSE expr */ yytestcase(yyruleno==208); +{yymsp[-1].minor.yy182 = yymsp[0].minor.yy182;} + break; + case 120: /* on_opt ::= */ + case 135: /* having_opt ::= */ yytestcase(yyruleno==135); + case 137: /* limit_opt ::= */ yytestcase(yyruleno==137); + case 142: /* where_opt ::= */ yytestcase(yyruleno==142); + case 209: /* case_else ::= */ yytestcase(yyruleno==209); + case 211: /* case_operand ::= */ yytestcase(yyruleno==211); +{yymsp[1].minor.yy182 = 0;} + break; + case 122: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 115: /* indexed_opt ::= NOT INDEXED */ + case 123: /* indexed_opt ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 116: /* using_opt ::= USING LP idlist RP */ -{yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} + case 124: /* using_opt ::= USING LP idlist RP */ +{yymsp[-3].minor.yy510 = yymsp[-1].minor.yy510;} break; - case 117: /* using_opt ::= */ - case 145: /* idlist_opt ::= */ yytestcase(yyruleno==145); -{yymsp[1].minor.yy254 = 0;} + case 125: /* using_opt ::= */ + case 157: /* idlist_opt ::= */ yytestcase(yyruleno==157); +{yymsp[1].minor.yy510 = 0;} break; - case 119: /* orderby_opt ::= ORDER BY sortlist */ - case 126: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==126); -{yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;} + case 127: /* orderby_opt ::= ORDER BY sortlist */ + case 134: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==134); +{yymsp[-2].minor.yy232 = yymsp[0].minor.yy232;} break; - case 120: /* sortlist ::= sortlist COMMA expr sortorder */ + case 128: /* sortlist ::= sortlist COMMA expr sortorder */ { - yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy190.pExpr); - sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy148,yymsp[0].minor.yy194); + yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232,yymsp[-1].minor.yy182); + sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy232,yymsp[0].minor.yy502); } break; - case 121: /* sortlist ::= expr sortorder */ + case 129: /* sortlist ::= expr sortorder */ { - yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy190.pExpr); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy148,yymsp[0].minor.yy194); + yymsp[-1].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy182); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy232,yymsp[0].minor.yy502); } break; - case 122: /* sortorder ::= ASC */ -{yymsp[0].minor.yy194 = SQLITE_SO_ASC;} + case 130: /* sortorder ::= ASC */ +{yymsp[0].minor.yy502 = SQLITE_SO_ASC;} break; - case 123: /* sortorder ::= DESC */ -{yymsp[0].minor.yy194 = SQLITE_SO_DESC;} + case 131: /* sortorder ::= DESC */ +{yymsp[0].minor.yy502 = SQLITE_SO_DESC;} break; - case 124: /* sortorder ::= */ -{yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;} + case 132: /* sortorder ::= */ +{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;} break; - case 129: /* limit_opt ::= */ -{yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;} + case 138: /* limit_opt ::= LIMIT expr */ +{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,0);} break; - case 130: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yymsp[-1].minor.yy354.pOffset = 0;} + case 139: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);} break; - case 131: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;} + case 140: /* limit_opt ::= LIMIT expr COMMA expr */ +{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,yymsp[-2].minor.yy182);} break; - case 132: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;} - break; - case 133: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ + case 141: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy427, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy427,yymsp[0].minor.yy182,0,0); } break; - case 136: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 144: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ { - sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy427, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy232,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy427,yymsp[-1].minor.yy232,yymsp[0].minor.yy182,yymsp[-5].minor.yy502,0,0,0); } break; - case 137: /* setlist ::= setlist COMMA nm EQ expr */ + case 145: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[0].minor.yy182); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, 1); } break; - case 138: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + case 146: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); + yymsp[-6].minor.yy232 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy232, yymsp[-3].minor.yy510, yymsp[0].minor.yy182); } break; - case 139: /* setlist ::= nm EQ expr */ + case 147: /* setlist ::= nm EQ expr */ { - yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr); - sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy232 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy182); + sqlite3ExprListSetName(pParse, yylhsminor.yy232, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy148 = yylhsminor.yy148; + yymsp[-2].minor.yy232 = yylhsminor.yy232; break; - case 140: /* setlist ::= LP idlist RP EQ expr */ + case 148: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); + yymsp[-4].minor.yy232 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy510, yymsp[0].minor.yy182); } break; - case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 149: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); - sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194); + sqlite3Insert(pParse, yymsp[-3].minor.yy427, yymsp[-1].minor.yy399, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, yymsp[0].minor.yy198); } break; - case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ { - sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); - sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); + sqlite3Insert(pParse, yymsp[-3].minor.yy427, 0, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, 0); } break; - case 146: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} + case 151: /* upsert ::= */ +{ yymsp[1].minor.yy198 = 0; } break; - case 147: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} + case 152: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ +{ yymsp[-10].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy232,yymsp[-5].minor.yy182,yymsp[-1].minor.yy232,yymsp[0].minor.yy182);} break; - case 148: /* idlist ::= nm */ -{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ +{ yymsp[-7].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy232,yymsp[-2].minor.yy182,0,0); } break; - case 149: /* expr ::= LP expr RP */ -{spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} + case 154: /* upsert ::= ON CONFLICT DO NOTHING */ +{ yymsp[-3].minor.yy198 = sqlite3UpsertNew(pParse->db,0,0,0,0); } break; - case 150: /* expr ::= ID|INDEXED */ - case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); -{spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 158: /* idlist_opt ::= LP idlist RP */ +{yymsp[-2].minor.yy510 = yymsp[-1].minor.yy510;} break; - case 152: /* expr ::= nm DOT nm */ + case 159: /* idlist ::= idlist COMMA nm */ +{yymsp[-2].minor.yy510 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy510,&yymsp[0].minor.yy0);} + break; + case 160: /* idlist ::= nm */ +{yymsp[0].minor.yy510 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + break; + case 161: /* expr ::= LP expr RP */ +{yymsp[-2].minor.yy182 = yymsp[-1].minor.yy182;} + break; + case 162: /* expr ::= ID|INDEXED */ + case 163: /* expr ::= JOIN_KW */ yytestcase(yyruleno==163); +{yymsp[0].minor.yy182=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 164: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); - spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } + yymsp[-2].minor.yy182 = yylhsminor.yy182; break; - case 153: /* expr ::= nm DOT nm DOT nm */ + case 165: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); - spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } + yymsp[-4].minor.yy182 = yylhsminor.yy182; break; - case 154: /* term ::= NULL|FLOAT|BLOB */ - case 155: /* term ::= STRING */ yytestcase(yyruleno==155); -{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 166: /* term ::= NULL|FLOAT|BLOB */ + case 167: /* term ::= STRING */ yytestcase(yyruleno==167); +{yymsp[0].minor.yy182=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 156: /* term ::= INTEGER */ + case 168: /* term ::= INTEGER */ { - yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); - yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; - yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; + yylhsminor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); } - yymsp[0].minor.yy190 = yylhsminor.yy190; + yymsp[0].minor.yy182 = yylhsminor.yy182; break; - case 157: /* expr ::= VARIABLE */ + case 169: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); + yymsp[0].minor.yy182 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy182, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers ** in the virtual machine. #N is the N-th register. */ Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ assert( t.n>=2 ); - spanSet(&yymsp[0].minor.yy190, &t, &t); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy190.pExpr = 0; + yymsp[0].minor.yy182 = 0; }else{ - yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); + yymsp[0].minor.yy182 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy182 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy182->iTable); } } } break; - case 158: /* expr ::= expr COLLATE ID|STRING */ + case 170: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); - yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yymsp[-2].minor.yy182 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy182, &yymsp[0].minor.yy0, 1); } break; - case 159: /* expr ::= CAST LP expr AS typetoken RP */ + case 171: /* expr ::= CAST LP expr AS typetoken RP */ { - spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); + yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy182, yymsp[-3].minor.yy182, 0); } break; - case 160: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 172: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + if( yymsp[-1].minor.yy232 && yymsp[-1].minor.yy232->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); - spanSet(&yylhsminor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy194==SF_Distinct && yylhsminor.yy190.pExpr ){ - yylhsminor.yy190.pExpr->flags |= EP_Distinct; + yylhsminor.yy182 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy232, &yymsp[-4].minor.yy0); + if( yymsp[-2].minor.yy502==SF_Distinct && yylhsminor.yy182 ){ + yylhsminor.yy182->flags |= EP_Distinct; } } - yymsp[-4].minor.yy190 = yylhsminor.yy190; + yymsp[-4].minor.yy182 = yylhsminor.yy182; break; - case 161: /* expr ::= ID|INDEXED LP STAR RP */ + case 173: /* expr ::= ID|INDEXED LP STAR RP */ { - yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); } - yymsp[-3].minor.yy190 = yylhsminor.yy190; + yymsp[-3].minor.yy182 = yylhsminor.yy182; break; - case 162: /* term ::= CTIME_KW */ + case 174: /* term ::= CTIME_KW */ { - yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); - spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy190 = yylhsminor.yy190; + yymsp[0].minor.yy182 = yylhsminor.yy182; break; - case 163: /* expr ::= LP nexprlist COMMA expr RP */ + case 175: /* expr ::= LP nexprlist COMMA expr RP */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); - yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yylhsminor.yy190.pExpr ){ - yylhsminor.yy190.pExpr->x.pList = pList; - spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy232, yymsp[-1].minor.yy182); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy182 ){ + yymsp[-4].minor.yy182->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } } - yymsp[-4].minor.yy190 = yylhsminor.yy190; break; - case 164: /* expr ::= expr AND expr */ - case 165: /* expr ::= expr OR expr */ yytestcase(yyruleno==165); - case 166: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==166); - case 167: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==167); - case 168: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==168); - case 169: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==169); - case 170: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==170); - case 171: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==171); -{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} + case 176: /* expr ::= expr AND expr */ + case 177: /* expr ::= expr OR expr */ yytestcase(yyruleno==177); + case 178: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==178); + case 179: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==179); + case 180: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==180); + case 181: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==181); + case 182: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==182); + case 183: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==183); +{yymsp[-2].minor.yy182=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);} break; - case 172: /* likeop ::= NOT LIKE_KW|MATCH */ + case 184: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 173: /* expr ::= expr likeop expr */ + case 185: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); - yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); - exprNot(pParse, bNot, &yymsp[-2].minor.yy190); - yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; - if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy182); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy182); + yymsp[-2].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); + if( bNot ) yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy182, 0); + if( yymsp[-2].minor.yy182 ) yymsp[-2].minor.yy182->flags |= EP_InfixFunc; } break; - case 174: /* expr ::= expr likeop expr ESCAPE expr */ + case 186: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); - exprNot(pParse, bNot, &yymsp[-4].minor.yy190); - yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; - if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy182); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182); + yymsp[-4].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); + if( bNot ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0); + if( yymsp[-4].minor.yy182 ) yymsp[-4].minor.yy182->flags |= EP_InfixFunc; } break; - case 175: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} + case 187: /* expr ::= expr ISNULL|NOTNULL */ +{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy182,0);} break; - case 176: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} + case 188: /* expr ::= expr NOT NULL */ +{yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy182,0);} break; - case 177: /* expr ::= expr IS expr */ + case 189: /* expr ::= expr IS expr */ { - spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); + yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy182,yymsp[0].minor.yy182); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-2].minor.yy182, TK_ISNULL); } break; - case 178: /* expr ::= expr IS NOT expr */ + case 190: /* expr ::= expr IS NOT expr */ { - spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); + yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy182,yymsp[0].minor.yy182); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-3].minor.yy182, TK_NOTNULL); } break; - case 179: /* expr ::= NOT expr */ - case 180: /* expr ::= BITNOT expr */ yytestcase(yyruleno==180); -{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 191: /* expr ::= NOT expr */ + case 192: /* expr ::= BITNOT expr */ yytestcase(yyruleno==192); +{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy182, 0);/*A-overwrites-B*/} break; - case 181: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 193: /* expr ::= MINUS expr */ +{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy182, 0);} break; - case 182: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 194: /* expr ::= PLUS expr */ +{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy182, 0);} break; - case 183: /* between_op ::= BETWEEN */ - case 186: /* in_op ::= IN */ yytestcase(yyruleno==186); -{yymsp[0].minor.yy194 = 0;} + case 195: /* between_op ::= BETWEEN */ + case 198: /* in_op ::= IN */ yytestcase(yyruleno==198); +{yymsp[0].minor.yy502 = 0;} break; - case 185: /* expr ::= expr between_op expr AND expr */ + case 197: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); - if( yymsp[-4].minor.yy190.pExpr ){ - yymsp[-4].minor.yy190.pExpr->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy182, 0); + if( yymsp[-4].minor.yy182 ){ + yymsp[-4].minor.yy182->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); - yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0); } break; - case 188: /* expr ::= expr in_op LP exprlist RP */ + case 200: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy148==0 ){ + if( yymsp[-1].minor.yy232==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -139994,9 +144771,9 @@ static void yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1); - }else if( yymsp[-1].minor.yy148->nExpr==1 ){ + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy182); + yymsp[-4].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy502],1); + }else if( yymsp[-1].minor.yy232->nExpr==1 ){ /* Expressions of the form: ** ** expr1 IN (?1) @@ -140013,201 +144790,195 @@ static void yy_reduce( ** affinity or the collating sequence to use for comparison. Otherwise, ** the semantics would be subtly different from IN or NOT IN. */ - Expr *pRHS = yymsp[-1].minor.yy148->a[0].pExpr; - yymsp[-1].minor.yy148->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); + Expr *pRHS = yymsp[-1].minor.yy232->a[0].pExpr; + yymsp[-1].minor.yy232->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232); /* pRHS cannot be NULL because a malloc error would have been detected ** before now and control would have never reached this point */ if( ALWAYS(pRHS) ){ pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_NE : TK_EQ, yymsp[-4].minor.yy182, pRHS); }else{ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); - if( yymsp[-4].minor.yy190.pExpr ){ - yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0); + if( yymsp[-4].minor.yy182 ){ + yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy232; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232); } - exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0); } - yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 189: /* expr ::= LP select RP */ + case 201: /* expr ::= LP select RP */ { - spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); + yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy182, yymsp[-1].minor.yy399); } break; - case 190: /* expr ::= expr in_op LP select RP */ + case 202: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); - exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); - yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, yymsp[-1].minor.yy399); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0); } break; - case 191: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 203: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); - Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); - exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); - yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; + Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); + if( yymsp[0].minor.yy232 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy232); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, pSelect); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0); } break; - case 192: /* expr ::= EXISTS LP select RP */ + case 204: /* expr ::= EXISTS LP select RP */ { Expr *p; - spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); + p = yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy399); } break; - case 193: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 205: /* expr ::= CASE case_operand case_exprlist case_else END */ { - spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); - if( yymsp[-4].minor.yy190.pExpr ){ - yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); + yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy182, 0); + if( yymsp[-4].minor.yy182 ){ + yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy182 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[-1].minor.yy182) : yymsp[-2].minor.yy232; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy232); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy182); } } break; - case 194: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 206: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); - yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); + yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[-2].minor.yy182); + yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[0].minor.yy182); } break; - case 195: /* case_exprlist ::= WHEN expr THEN expr */ + case 207: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); - yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); + yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182); + yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232, yymsp[0].minor.yy182); } break; - case 198: /* case_operand ::= expr */ -{yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} + case 210: /* case_operand ::= expr */ +{yymsp[0].minor.yy182 = yymsp[0].minor.yy182; /*A-overwrites-X*/} break; - case 201: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} + case 213: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[0].minor.yy182);} break; - case 202: /* nexprlist ::= expr */ -{yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} + case 214: /* nexprlist ::= expr */ +{yymsp[0].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy182); /*A-overwrites-Y*/} break; - case 204: /* paren_exprlist ::= LP exprlist RP */ - case 209: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==209); -{yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} + case 216: /* paren_exprlist ::= LP exprlist RP */ + case 221: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==221); +{yymsp[-2].minor.yy232 = yymsp[-1].minor.yy232;} break; - case 205: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 217: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy232, yymsp[-10].minor.yy502, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy182, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF); } break; - case 206: /* uniqueflag ::= UNIQUE */ - case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246); -{yymsp[0].minor.yy194 = OE_Abort;} + case 218: /* uniqueflag ::= UNIQUE */ + case 258: /* raisetype ::= ABORT */ yytestcase(yyruleno==258); +{yymsp[0].minor.yy502 = OE_Abort;} break; - case 207: /* uniqueflag ::= */ -{yymsp[1].minor.yy194 = OE_None;} + case 219: /* uniqueflag ::= */ +{yymsp[1].minor.yy502 = OE_None;} break; - case 210: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 222: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); + yymsp[-4].minor.yy232 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); } break; - case 211: /* eidlist ::= nm collate sortorder */ + case 223: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ + yymsp[-2].minor.yy232 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/ } break; - case 214: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} + case 226: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy427, yymsp[-1].minor.yy502);} break; - case 215: /* cmd ::= VACUUM */ + case 227: /* cmd ::= VACUUM */ {sqlite3Vacuum(pParse,0);} break; - case 216: /* cmd ::= VACUUM nm */ + case 228: /* cmd ::= VACUUM nm */ {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} break; - case 217: /* cmd ::= PRAGMA nm dbnm */ + case 229: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 218: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 230: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 219: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 231: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 220: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 232: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 221: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 233: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 224: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 236: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy47, &all); } break; - case 225: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 237: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy300.a, yymsp[-4].minor.yy300.b, yymsp[-2].minor.yy427, yymsp[0].minor.yy182, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 226: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/ } + case 238: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 227: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy194 = TK_INSTEAD;} + case 239: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy502 = TK_INSTEAD;} break; - case 228: /* trigger_time ::= */ -{ yymsp[1].minor.yy194 = TK_BEFORE; } + case 240: /* trigger_time ::= */ +{ yymsp[1].minor.yy502 = TK_BEFORE; } break; - case 229: /* trigger_event ::= DELETE|INSERT */ - case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230); -{yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} + case 241: /* trigger_event ::= DELETE|INSERT */ + case 242: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==242); +{yymsp[0].minor.yy300.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy300.b = 0;} break; - case 231: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} + case 243: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy300.a = TK_UPDATE; yymsp[-2].minor.yy300.b = yymsp[0].minor.yy510;} break; - case 232: /* when_clause ::= */ - case 251: /* key_opt ::= */ yytestcase(yyruleno==251); -{ yymsp[1].minor.yy72 = 0; } + case 244: /* when_clause ::= */ + case 263: /* key_opt ::= */ yytestcase(yyruleno==263); +{ yymsp[1].minor.yy182 = 0; } break; - case 233: /* when_clause ::= WHEN expr */ - case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252); -{ yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } + case 245: /* when_clause ::= WHEN expr */ + case 264: /* key_opt ::= KEY expr */ yytestcase(yyruleno==264); +{ yymsp[-1].minor.yy182 = yymsp[0].minor.yy182; } break; - case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 246: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy145!=0 ); - yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; - yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; + assert( yymsp[-2].minor.yy47!=0 ); + yymsp[-2].minor.yy47->pLast->pNext = yymsp[-1].minor.yy47; + yymsp[-2].minor.yy47->pLast = yymsp[-1].minor.yy47; } break; - case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 247: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy145!=0 ); - yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; + assert( yymsp[-1].minor.yy47!=0 ); + yymsp[-1].minor.yy47->pLast = yymsp[-1].minor.yy47; } break; - case 236: /* trnm ::= nm DOT nm */ + case 248: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -140215,196 +144986,196 @@ static void yy_reduce( "statements within triggers"); } break; - case 237: /* tridxby ::= INDEXED BY nm */ + case 249: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 238: /* tridxby ::= NOT INDEXED */ + case 250: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} + case 251: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ +{yylhsminor.yy47 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy182, yymsp[-6].minor.yy502, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy36);} + yymsp[-7].minor.yy47 = yylhsminor.yy47; break; - case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ -{yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} - break; - case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} - break; - case 242: /* trigger_cmd ::= select */ -{yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} - break; - case 243: /* expr ::= RAISE LP IGNORE RP */ + case 252: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy190.pExpr ){ - yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; + yylhsminor.yy47 = sqlite3TriggerInsertStep(pParse->db,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy510,yymsp[-2].minor.yy399,yymsp[-6].minor.yy502,yymsp[-1].minor.yy198,yymsp[-7].minor.yy36,yymsp[0].minor.yy36);/*yylhsminor.yy47-overwrites-yymsp[-6].minor.yy502*/ +} + yymsp[-7].minor.yy47 = yylhsminor.yy47; + break; + case 253: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy47 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy182, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy36);} + yymsp[-5].minor.yy47 = yylhsminor.yy47; + break; + case 254: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy47 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy399, yymsp[-2].minor.yy36, yymsp[0].minor.yy36); /*yylhsminor.yy47-overwrites-yymsp[-1].minor.yy399*/} + yymsp[-2].minor.yy47 = yylhsminor.yy47; + break; + case 255: /* expr ::= RAISE LP IGNORE RP */ +{ + yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy182 ){ + yymsp[-3].minor.yy182->affinity = OE_Ignore; } } break; - case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 256: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); - if( yymsp[-5].minor.yy190.pExpr ) { - yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; + yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy182 ) { + yymsp[-5].minor.yy182->affinity = (char)yymsp[-3].minor.yy502; } } break; - case 245: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy194 = OE_Rollback;} + case 257: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy502 = OE_Rollback;} break; - case 247: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy194 = OE_Fail;} + case 259: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy502 = OE_Fail;} break; - case 248: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 260: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy427,yymsp[-1].minor.yy502); } break; - case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 261: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); + sqlite3Attach(pParse, yymsp[-3].minor.yy182, yymsp[-1].minor.yy182, yymsp[0].minor.yy182); } break; - case 250: /* cmd ::= DETACH database_kw_opt expr */ + case 262: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); + sqlite3Detach(pParse, yymsp[0].minor.yy182); } break; - case 253: /* cmd ::= REINDEX */ + case 265: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 254: /* cmd ::= REINDEX nm dbnm */ + case 266: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 255: /* cmd ::= ANALYZE */ + case 267: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 256: /* cmd ::= ANALYZE nm dbnm */ + case 268: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 269: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy0); } break; - case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 270: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 259: /* add_column_fullname ::= fullname */ + case 271: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy427); } break; - case 260: /* cmd ::= create_vtab */ + case 272: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 261: /* cmd ::= create_vtab LP vtabarglist RP */ + case 273: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 274: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502); } break; - case 263: /* vtabarg ::= */ + case 275: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 264: /* vtabargtoken ::= ANY */ - case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265); - case 266: /* lp ::= LP */ yytestcase(yyruleno==266); + case 276: /* vtabargtoken ::= ANY */ + case 277: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==277); + case 278: /* lp ::= LP */ yytestcase(yyruleno==278); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 267: /* with ::= */ -{yymsp[1].minor.yy285 = 0;} + case 279: /* with ::= WITH wqlist */ + case 280: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==280); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy91, 1); } break; - case 268: /* with ::= WITH wqlist */ -{ yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } - break; - case 269: /* with ::= WITH RECURSIVE wqlist */ -{ yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } - break; - case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 281: /* wqlist ::= nm eidlist_opt AS LP select RP */ { - yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ + yymsp[-5].minor.yy91 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399); /*A-overwrites-X*/ } break; - case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 282: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { - yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); + yymsp[-7].minor.yy91 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy91, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399); } break; default: - /* (272) input ::= cmdlist */ yytestcase(yyruleno==272); - /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273); - /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274); - /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275); - /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276); - /* (277) explain ::= */ yytestcase(yyruleno==277); - /* (278) trans_opt ::= */ yytestcase(yyruleno==278); - /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279); - /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280); - /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281); - /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282); - /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283); - /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284); - /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285); - /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286); - /* (287) nm ::= STRING */ yytestcase(yyruleno==287); - /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288); - /* (289) typetoken ::= typename */ yytestcase(yyruleno==289); - /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290); - /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291); - /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); - /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293); - /* (294) carglist ::= */ yytestcase(yyruleno==294); - /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295); - /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296); - /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297); - /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298); - /* (299) tconscomma ::= */ yytestcase(yyruleno==299); - /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300); - /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301); - /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302); - /* (303) oneselect ::= values */ yytestcase(yyruleno==303); - /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304); - /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305); - /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306); - /* (307) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==307); - /* (308) exprlist ::= nexprlist */ yytestcase(yyruleno==308); - /* (309) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=309); - /* (310) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=310); - /* (311) nmnum ::= ON */ yytestcase(yyruleno==311); - /* (312) nmnum ::= DELETE */ yytestcase(yyruleno==312); - /* (313) nmnum ::= DEFAULT */ yytestcase(yyruleno==313); - /* (314) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==314); - /* (315) foreach_clause ::= */ yytestcase(yyruleno==315); - /* (316) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==316); - /* (317) trnm ::= nm */ yytestcase(yyruleno==317); - /* (318) tridxby ::= */ yytestcase(yyruleno==318); - /* (319) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==319); - /* (320) database_kw_opt ::= */ yytestcase(yyruleno==320); - /* (321) kwcolumn_opt ::= */ yytestcase(yyruleno==321); - /* (322) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==322); - /* (323) vtabarglist ::= vtabarg */ yytestcase(yyruleno==323); - /* (324) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==324); - /* (325) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==325); - /* (326) anylist ::= */ yytestcase(yyruleno==326); - /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); - /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); + /* (283) input ::= cmdlist */ yytestcase(yyruleno==283); + /* (284) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==284); + /* (285) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=285); + /* (286) ecmd ::= SEMI */ yytestcase(yyruleno==286); + /* (287) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==287); + /* (288) ecmd ::= explain cmdx */ yytestcase(yyruleno==288); + /* (289) trans_opt ::= */ yytestcase(yyruleno==289); + /* (290) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==290); + /* (291) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==291); + /* (292) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==292); + /* (293) savepoint_opt ::= */ yytestcase(yyruleno==293); + /* (294) cmd ::= create_table create_table_args */ yytestcase(yyruleno==294); + /* (295) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==295); + /* (296) columnlist ::= columnname carglist */ yytestcase(yyruleno==296); + /* (297) nm ::= ID|INDEXED */ yytestcase(yyruleno==297); + /* (298) nm ::= STRING */ yytestcase(yyruleno==298); + /* (299) nm ::= JOIN_KW */ yytestcase(yyruleno==299); + /* (300) typetoken ::= typename */ yytestcase(yyruleno==300); + /* (301) typename ::= ID|STRING */ yytestcase(yyruleno==301); + /* (302) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=302); + /* (303) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=303); + /* (304) carglist ::= carglist ccons */ yytestcase(yyruleno==304); + /* (305) carglist ::= */ yytestcase(yyruleno==305); + /* (306) ccons ::= NULL onconf */ yytestcase(yyruleno==306); + /* (307) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==307); + /* (308) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==308); + /* (309) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=309); + /* (310) tconscomma ::= */ yytestcase(yyruleno==310); + /* (311) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=311); + /* (312) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=312); + /* (313) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=313); + /* (314) oneselect ::= values */ yytestcase(yyruleno==314); + /* (315) sclp ::= selcollist COMMA */ yytestcase(yyruleno==315); + /* (316) as ::= ID|STRING */ yytestcase(yyruleno==316); + /* (317) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=317); + /* (318) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==318); + /* (319) exprlist ::= nexprlist */ yytestcase(yyruleno==319); + /* (320) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=320); + /* (321) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=321); + /* (322) nmnum ::= ON */ yytestcase(yyruleno==322); + /* (323) nmnum ::= DELETE */ yytestcase(yyruleno==323); + /* (324) nmnum ::= DEFAULT */ yytestcase(yyruleno==324); + /* (325) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==325); + /* (326) foreach_clause ::= */ yytestcase(yyruleno==326); + /* (327) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==327); + /* (328) trnm ::= nm */ yytestcase(yyruleno==328); + /* (329) tridxby ::= */ yytestcase(yyruleno==329); + /* (330) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==330); + /* (331) database_kw_opt ::= */ yytestcase(yyruleno==331); + /* (332) kwcolumn_opt ::= */ yytestcase(yyruleno==332); + /* (333) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==333); + /* (334) vtabarglist ::= vtabarg */ yytestcase(yyruleno==334); + /* (335) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==335); + /* (336) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==336); + /* (337) anylist ::= */ yytestcase(yyruleno==337); + /* (338) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==338); + /* (339) anylist ::= anylist ANY */ yytestcase(yyruleno==339); + /* (340) with ::= */ yytestcase(yyruleno==340); break; /********** End reduce actions ************************************************/ }; @@ -140420,16 +145191,12 @@ static void yy_reduce( /* It is not possible for a REDUCE to be followed by an error */ assert( yyact!=YY_ERROR_ACTION ); - if( yyact==YY_ACCEPT_ACTION ){ - yypParser->yytos += yysize; - yy_accept(yypParser); - }else{ - yymsp += yysize+1; - yypParser->yytos = yymsp; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact); - } + yymsp += yysize+1; + yypParser->yytos = yymsp; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yypParser, yyact, "... then shift"); + return yyact; } /* @@ -140439,7 +145206,8 @@ static void yy_reduce( static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ - sqlite3ParserARG_FETCH; + sqlite3ParserARG_FETCH + sqlite3ParserCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); @@ -140450,7 +145218,8 @@ static void yy_parse_failed( ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserCTX_STORE } #endif /* YYNOERRORRECOVERY */ @@ -140462,15 +145231,20 @@ static void yy_syntax_error( int yymajor, /* The major type of the error token */ sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ ){ - sqlite3ParserARG_FETCH; + sqlite3ParserARG_FETCH + sqlite3ParserCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ - assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); + if( TOKEN.z[0] ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); + }else{ + sqlite3ErrorMsg(pParse, "incomplete input"); + } /************ End %syntax_error code ******************************************/ - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserCTX_STORE } /* @@ -140479,7 +145253,8 @@ static void yy_syntax_error( static void yy_accept( yyParser *yypParser /* The parser */ ){ - sqlite3ParserARG_FETCH; + sqlite3ParserARG_FETCH + sqlite3ParserCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); @@ -140493,7 +145268,8 @@ static void yy_accept( ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ /*********** End %parse_accept code *******************************************/ - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3ParserCTX_STORE } /* The main parser program. @@ -140522,38 +145298,51 @@ SQLITE_PRIVATE void sqlite3Parser( sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - unsigned int yyact; /* The parser action. */ + YYACTIONTYPE yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif - yyParser *yypParser; /* The parser */ + yyParser *yypParser = (yyParser*)yyp; /* The parser */ + sqlite3ParserCTX_FETCH + sqlite3ParserARG_STORE - yypParser = (yyParser*)yyp; assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif - sqlite3ParserARG_STORE; + yyact = yypParser->yytos->stateno; #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + if( yyact < YY_MIN_REDUCE ){ + fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", + yyTracePrompt,yyTokenName[yymajor],yyact); + }else{ + fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", + yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); + } } #endif do{ - yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyact <= YY_MAX_SHIFTREDUCE ){ + assert( yyact==yypParser->yytos->stateno ); + yyact = yy_find_shift_action(yymajor,yyact); + if( yyact >= YY_MIN_REDUCE ){ + yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, + yyminor sqlite3ParserCTX_PARAM); + }else if( yyact <= YY_MAX_SHIFTREDUCE ){ yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif - yymajor = YYNOCODE; - }else if( yyact <= YY_MAX_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE); + break; + }else if( yyact==YY_ACCEPT_ACTION ){ + yypParser->yytos--; + yy_accept(yypParser); + return; }else{ assert( yyact == YY_ERROR_ACTION ); yyminorunion.yy0 = yyminor; @@ -140620,6 +145409,8 @@ SQLITE_PRIVATE void sqlite3Parser( } yypParser->yyerrcnt = 3; yyerrorhit = 1; + if( yymajor==YYNOCODE ) break; + yyact = yypParser->yytos->stateno; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax @@ -140630,8 +145421,7 @@ SQLITE_PRIVATE void sqlite3Parser( */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - + break; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -140653,10 +145443,10 @@ SQLITE_PRIVATE void sqlite3Parser( yypParser->yyerrcnt = -1; #endif } - yymajor = YYNOCODE; + break; #endif } - }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); + }while( yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; @@ -140833,19 +145623,19 @@ const unsigned char ebcdicToAscii[] = { ** is substantially reduced. This is important for embedded applications ** on platforms with limited memory. */ -/* Hash score: 182 */ -/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */ +/* Hash score: 185 */ +/* zKWText[] encodes 845 bytes of keyword text in 561 bytes */ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ /* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ -/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ -/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ -/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ -/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ -/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ -/* VACUUMVIEWINITIALLY */ -static const char zKWText[553] = { +/* BETWEENOTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATE */ +/* DETACHIMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUES */ +/* VIRTUALIMITWHENOTNULLWHERENAMEAFTEREPLACEANDEFAULT */ +/* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */ +/* RIMARYDEFERREDISTINCTDORDERESTRICTDROPFAILFROMFULLIFISNULL */ +/* RIGHTROLLBACKROWUNIONUSINGVACUUMVIEWINITIALLY */ +static const char zKWText[560] = { 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', @@ -140859,82 +145649,83 @@ static const char zKWText[553] = { 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', - 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', - 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', - 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', - 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', - 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', - 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', - 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', - 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', - 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', - 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', - 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', - 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', - 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', - 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', - 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', - 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', - 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', - 'V','I','E','W','I','N','I','T','I','A','L','L','Y', + 'B','E','T','W','E','E','N','O','T','H','I','N','G','L','O','B','Y','C', + 'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L', + 'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D', + 'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E', + 'J','O','I','N','S','E','R','T','L','I','K','E','M','A','T','C','H','P', + 'L','A','N','A','L','Y','Z','E','P','R','A','G','M','A','B','O','R','T', + 'V','A','L','U','E','S','V','I','R','T','U','A','L','I','M','I','T','W', + 'H','E','N','O','T','N','U','L','L','W','H','E','R','E','N','A','M','E', + 'A','F','T','E','R','E','P','L','A','C','E','A','N','D','E','F','A','U', + 'L','T','A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S', + 'T','C','O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L', + 'I','C','T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I', + 'M','E','S','T','A','M','P','R','I','M','A','R','Y','D','E','F','E','R', + 'R','E','D','I','S','T','I','N','C','T','D','O','R','D','E','R','E','S', + 'T','R','I','C','T','D','R','O','P','F','A','I','L','F','R','O','M','F', + 'U','L','L','I','F','I','S','N','U','L','L','R','I','G','H','T','R','O', + 'L','L','B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N', + 'G','V','A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L', + 'L','Y', }; /* aKWHash[i] is the hash value for the i-th keyword */ static const unsigned char aKWHash[127] = { - 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, - 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, - 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, - 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, - 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, - 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, - 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, - 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, - 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, - 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, + 74, 108, 119, 72, 0, 45, 0, 0, 81, 0, 76, 61, 0, + 42, 12, 77, 15, 0, 118, 84, 54, 116, 0, 19, 0, 0, + 123, 0, 121, 111, 0, 22, 96, 0, 9, 0, 0, 68, 69, + 0, 67, 6, 0, 48, 93, 105, 0, 120, 104, 0, 0, 44, + 0, 106, 24, 0, 17, 0, 124, 53, 23, 0, 5, 62, 25, + 99, 0, 0, 126, 112, 60, 125, 57, 28, 55, 0, 94, 0, + 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 91, 115, 14, + 39, 114, 0, 80, 0, 109, 92, 90, 32, 0, 122, 79, 117, + 86, 46, 83, 0, 0, 97, 40, 59, 110, 0, 36, 0, 0, + 29, 0, 89, 87, 88, 0, 20, 85, 0, 56, }; /* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 ** then the i-th keyword has no more hash collisions. Otherwise, ** the next keyword with the same hash is aKWHash[i]-1. */ -static const unsigned char aKWNext[124] = { +static const unsigned char aKWNext[126] = { 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, - 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, - 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, - 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, - 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, - 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, - 73, 83, 0, 35, 68, 0, 0, + 0, 43, 3, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 64, 0, 0, 65, 0, 41, 0, 38, 0, 0, 0, + 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 63, 31, + 52, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70, + 78, 0, 8, 0, 18, 51, 0, 107, 101, 0, 113, 0, 73, + 27, 37, 71, 82, 0, 35, 66, 0, 0, }; /* aKWLen[i] is the length (in bytes) of the i-th keyword */ -static const unsigned char aKWLen[124] = { +static const unsigned char aKWLen[126] = { 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, - 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, - 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, - 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, - 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, - 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, - 3, 5, 5, 6, 4, 9, 3, + 6, 6, 5, 6, 5, 5, 9, 7, 7, 4, 2, 7, 3, + 6, 4, 7, 6, 12, 6, 9, 4, 6, 4, 5, 4, 7, + 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 6, 5, + 7, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, + 7, 8, 8, 2, 2, 5, 8, 4, 4, 4, 4, 2, 6, + 5, 8, 3, 5, 5, 6, 4, 9, 3, }; /* aKWOffset[i] is the index into zKWText[] of the start of ** the text for the i-th keyword. */ -static const unsigned short int aKWOffset[124] = { +static const unsigned short int aKWOffset[126] = { 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, - 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, - 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, - 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, - 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, - 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, - 521, 524, 529, 534, 540, 544, 549, + 199, 204, 209, 212, 218, 221, 225, 234, 240, 246, 249, 251, 252, + 256, 262, 266, 273, 279, 291, 297, 306, 308, 314, 318, 323, 325, + 332, 337, 342, 348, 354, 359, 362, 362, 362, 365, 369, 372, 378, + 382, 389, 391, 398, 400, 402, 411, 415, 421, 427, 435, 440, 440, + 456, 463, 470, 471, 478, 479, 483, 491, 495, 499, 503, 507, 509, + 515, 520, 528, 531, 536, 541, 547, 551, 556, }; /* aKWCode[i] is the parser symbol code for the i-th keyword */ -static const unsigned char aKWCode[124] = { +static const unsigned char aKWCode[126] = { TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, @@ -140947,19 +145738,20 @@ static const unsigned char aKWCode[124] = { TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, - TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, - TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, - TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, - TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, - TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, - TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, - TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, - TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, - TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, - TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, - TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, - TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, - TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, + TK_NOTHING, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, + TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, + TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_LIKE_KW, + TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, + TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_NOTNULL, + TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RENAME, + TK_AFTER, TK_REPLACE, TK_AND, TK_DEFAULT, TK_AUTOINCR, + TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, + TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, + TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DO, TK_ORDER, + TK_RESTRICT, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, + TK_IF, TK_ISNULL, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, + TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, + TK_ALL, }; /* Check to see if z[0..n-1] is a keyword. If it is, write the ** parser symbol code for that keyword into *pType. Always @@ -141040,70 +145832,72 @@ static int keywordCode(const char *z, int n, int *pType){ testcase( i==57 ); /* INNER */ testcase( i==58 ); /* RECURSIVE */ testcase( i==59 ); /* BETWEEN */ - testcase( i==60 ); /* NOTNULL */ - testcase( i==61 ); /* NOT */ - testcase( i==62 ); /* NO */ - testcase( i==63 ); /* NULL */ - testcase( i==64 ); /* LIKE */ - testcase( i==65 ); /* CASCADE */ - testcase( i==66 ); /* ASC */ - testcase( i==67 ); /* DELETE */ - testcase( i==68 ); /* CASE */ - testcase( i==69 ); /* COLLATE */ - testcase( i==70 ); /* CREATE */ - testcase( i==71 ); /* CURRENT_DATE */ - testcase( i==72 ); /* DETACH */ - testcase( i==73 ); /* IMMEDIATE */ - testcase( i==74 ); /* JOIN */ - testcase( i==75 ); /* INSERT */ - testcase( i==76 ); /* MATCH */ - testcase( i==77 ); /* PLAN */ - testcase( i==78 ); /* ANALYZE */ - testcase( i==79 ); /* PRAGMA */ - testcase( i==80 ); /* ABORT */ - testcase( i==81 ); /* VALUES */ - testcase( i==82 ); /* VIRTUAL */ - testcase( i==83 ); /* LIMIT */ - testcase( i==84 ); /* WHEN */ - testcase( i==85 ); /* WHERE */ - testcase( i==86 ); /* RENAME */ - testcase( i==87 ); /* AFTER */ - testcase( i==88 ); /* REPLACE */ - testcase( i==89 ); /* AND */ - testcase( i==90 ); /* DEFAULT */ - testcase( i==91 ); /* AUTOINCREMENT */ - testcase( i==92 ); /* TO */ - testcase( i==93 ); /* IN */ - testcase( i==94 ); /* CAST */ - testcase( i==95 ); /* COLUMN */ - testcase( i==96 ); /* COMMIT */ - testcase( i==97 ); /* CONFLICT */ - testcase( i==98 ); /* CROSS */ - testcase( i==99 ); /* CURRENT_TIMESTAMP */ - testcase( i==100 ); /* CURRENT_TIME */ - testcase( i==101 ); /* PRIMARY */ - testcase( i==102 ); /* DEFERRED */ - testcase( i==103 ); /* DISTINCT */ - testcase( i==104 ); /* IS */ - testcase( i==105 ); /* DROP */ - testcase( i==106 ); /* FAIL */ - testcase( i==107 ); /* FROM */ - testcase( i==108 ); /* FULL */ - testcase( i==109 ); /* GLOB */ - testcase( i==110 ); /* BY */ - testcase( i==111 ); /* IF */ - testcase( i==112 ); /* ISNULL */ - testcase( i==113 ); /* ORDER */ - testcase( i==114 ); /* RESTRICT */ - testcase( i==115 ); /* RIGHT */ - testcase( i==116 ); /* ROLLBACK */ - testcase( i==117 ); /* ROW */ - testcase( i==118 ); /* UNION */ - testcase( i==119 ); /* USING */ - testcase( i==120 ); /* VACUUM */ - testcase( i==121 ); /* VIEW */ - testcase( i==122 ); /* INITIALLY */ - testcase( i==123 ); /* ALL */ + testcase( i==60 ); /* NOTHING */ + testcase( i==61 ); /* GLOB */ + testcase( i==62 ); /* BY */ + testcase( i==63 ); /* CASCADE */ + testcase( i==64 ); /* ASC */ + testcase( i==65 ); /* DELETE */ + testcase( i==66 ); /* CASE */ + testcase( i==67 ); /* COLLATE */ + testcase( i==68 ); /* CREATE */ + testcase( i==69 ); /* CURRENT_DATE */ + testcase( i==70 ); /* DETACH */ + testcase( i==71 ); /* IMMEDIATE */ + testcase( i==72 ); /* JOIN */ + testcase( i==73 ); /* INSERT */ + testcase( i==74 ); /* LIKE */ + testcase( i==75 ); /* MATCH */ + testcase( i==76 ); /* PLAN */ + testcase( i==77 ); /* ANALYZE */ + testcase( i==78 ); /* PRAGMA */ + testcase( i==79 ); /* ABORT */ + testcase( i==80 ); /* VALUES */ + testcase( i==81 ); /* VIRTUAL */ + testcase( i==82 ); /* LIMIT */ + testcase( i==83 ); /* WHEN */ + testcase( i==84 ); /* NOTNULL */ + testcase( i==85 ); /* NOT */ + testcase( i==86 ); /* NO */ + testcase( i==87 ); /* NULL */ + testcase( i==88 ); /* WHERE */ + testcase( i==89 ); /* RENAME */ + testcase( i==90 ); /* AFTER */ + testcase( i==91 ); /* REPLACE */ + testcase( i==92 ); /* AND */ + testcase( i==93 ); /* DEFAULT */ + testcase( i==94 ); /* AUTOINCREMENT */ + testcase( i==95 ); /* TO */ + testcase( i==96 ); /* IN */ + testcase( i==97 ); /* CAST */ + testcase( i==98 ); /* COLUMN */ + testcase( i==99 ); /* COMMIT */ + testcase( i==100 ); /* CONFLICT */ + testcase( i==101 ); /* CROSS */ + testcase( i==102 ); /* CURRENT_TIMESTAMP */ + testcase( i==103 ); /* CURRENT_TIME */ + testcase( i==104 ); /* PRIMARY */ + testcase( i==105 ); /* DEFERRED */ + testcase( i==106 ); /* DISTINCT */ + testcase( i==107 ); /* IS */ + testcase( i==108 ); /* DO */ + testcase( i==109 ); /* ORDER */ + testcase( i==110 ); /* RESTRICT */ + testcase( i==111 ); /* DROP */ + testcase( i==112 ); /* FAIL */ + testcase( i==113 ); /* FROM */ + testcase( i==114 ); /* FULL */ + testcase( i==115 ); /* IF */ + testcase( i==116 ); /* ISNULL */ + testcase( i==117 ); /* RIGHT */ + testcase( i==118 ); /* ROLLBACK */ + testcase( i==119 ); /* ROW */ + testcase( i==120 ); /* UNION */ + testcase( i==121 ); /* USING */ + testcase( i==122 ); /* VACUUM */ + testcase( i==123 ); /* VIEW */ + testcase( i==124 ); /* INITIALLY */ + testcase( i==125 ); /* ALL */ *pType = aKWCode[i]; break; } @@ -141115,7 +145909,17 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ keywordCode((char*)z, n, &id); return id; } -#define SQLITE_N_KEYWORD 124 +#define SQLITE_N_KEYWORD 126 +SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ + if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; + *pzName = zKWText + aKWOffset[i]; + *pnName = aKWLen[i]; + return SQLITE_OK; +} +SQLITE_API int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; } +SQLITE_API int sqlite3_keyword_check(const char *zName, int nName){ + return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName); +} /************** End of keywordhash.h *****************************************/ /************** Continuing where we left off in tokenize.c *******************/ @@ -141472,9 +146276,9 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr /* sqlite3ParserTrace(stdout, "parser: "); */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK pEngine = &sEngine; - sqlite3ParserInit(pEngine); + sqlite3ParserInit(pEngine, pParse); #else - pEngine = sqlite3ParserAlloc(sqlite3Malloc); + pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); if( pEngine==0 ){ sqlite3OomFault(db); return SQLITE_NOMEM_BKPT; @@ -141502,7 +146306,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr }else{ tokenType = TK_SEMI; } - zSql -= n; + n = 0; } if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); @@ -141518,7 +146322,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr }else{ pParse->sLastToken.z = zSql; pParse->sLastToken.n = n; - sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); + sqlite3Parser(pEngine, tokenType, pParse->sLastToken); lastTokenParsed = tokenType; zSql += n; if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; @@ -141957,6 +146761,10 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); */ /* #include "sqlite3.h" */ +#ifdef SQLITE_OMIT_VIRTUALTABLE +# undef SQLITE_ENABLE_RTREE +#endif + #if 0 extern "C" { #endif /* __cplusplus */ @@ -141970,7 +146778,7 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); /************** End of rtree.h ***********************************************/ /************** Continuing where we left off in main.c ***********************/ #endif -#ifdef SQLITE_ENABLE_ICU +#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) /************** Include sqliteicu.h in the middle of main.c ******************/ /************** Begin file sqliteicu.h ***************************************/ /* @@ -142218,6 +147026,11 @@ SQLITE_API int sqlite3_initialize(void){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } +#ifdef SQLITE_ENABLE_DESERIALIZE + if( rc==SQLITE_OK ){ + rc = sqlite3MemdbInit(); + } +#endif if( rc==SQLITE_OK ){ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); @@ -142250,7 +147063,7 @@ SQLITE_API int sqlite3_initialize(void){ #ifndef NDEBUG #ifndef SQLITE_OMIT_FLOATING_POINT /* This section of code's only "output" is via assert() statements. */ - if ( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ u64 x = (((u64)1)<<63)-1; double y; assert(sizeof(x)==8); @@ -142616,6 +147429,17 @@ SQLITE_API int sqlite3_config(int op, ...){ break; } +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + case SQLITE_CONFIG_SORTERREF_SIZE: { + int iVal = va_arg(ap, int); + if( iVal<0 ){ + iVal = SQLITE_DEFAULT_SORTERREF_SIZE; + } + sqlite3GlobalConfig.szSorterRef = (u32)iVal; + break; + } +#endif /* SQLITE_ENABLE_SORTER_REFERENCES */ + default: { rc = SQLITE_ERROR; break; @@ -142796,6 +147620,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, + { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, + { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -143293,9 +148119,10 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; - case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; + case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; + case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; @@ -143415,6 +148242,8 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ /* SQLITE_FORMAT */ 0, /* SQLITE_RANGE */ "column index out of range", /* SQLITE_NOTADB */ "file is not a database", + /* SQLITE_NOTICE */ "notification message", + /* SQLITE_WARNING */ "warning message", }; const char *zErr = "unknown error"; switch( rc ){ @@ -143422,6 +148251,14 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ zErr = "abort due to ROLLBACK"; break; } + case SQLITE_ROW: { + zErr = "another row available"; + break; + } + case SQLITE_DONE: { + zErr = "no more rows available"; + break; + } default: { rc &= 0xff; if( ALWAYS(rc>=0) && rcbusyTimeout; + int tmout = db->busyTimeout; int delay, prior; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){ + if( count ){ + tmout = 0; + sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout); + return 0; + }else{ + return 1; + } + } +#else + UNUSED_PARAMETER(pFile); +#endif assert( count>=0 ); if( count < NDELAY ){ delay = delays[count]; @@ -143461,16 +148317,19 @@ static int sqliteDefaultBusyCallback( delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); } - if( prior + delay > timeout ){ - delay = timeout - prior; + if( prior + delay > tmout ){ + delay = tmout - prior; if( delay<=0 ) return 0; } sqlite3OsSleep(db->pVfs, delay*1000); return 1; #else + /* This case for unix systems that lack usleep() support. Sleeping + ** must be done in increments of whole seconds */ sqlite3 *db = (sqlite3 *)ptr; - int timeout = ((sqlite3 *)ptr)->busyTimeout; - if( (count+1)*1000 > timeout ){ + int tmout = ((sqlite3 *)ptr)->busyTimeout; + UNUSED_PARAMETER(pFile); + if( (count+1)*1000 > tmout ){ return 0; } sqlite3OsSleep(db->pVfs, 1000000); @@ -143481,14 +148340,25 @@ static int sqliteDefaultBusyCallback( /* ** Invoke the given busy handler. ** -** This routine is called when an operation failed with a lock. +** This routine is called when an operation failed to acquire a +** lock on VFS file pFile. +** ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ int rc; - if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; - rc = p->xFunc(p->pArg, p->nBusy); + if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; + if( p->bExtraFileArg ){ + /* Add an extra parameter with the pFile pointer to the end of the + ** callback argument list */ + int (*xTra)(void*,int,sqlite3_file*); + xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler; + rc = xTra(p->pBusyArg, p->nBusy, pFile); + }else{ + /* Legacy style busy handler callback */ + rc = p->xBusyHandler(p->pBusyArg, p->nBusy); + } if( rc==0 ){ p->nBusy = -1; }else{ @@ -143510,9 +148380,10 @@ SQLITE_API int sqlite3_busy_handler( if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); - db->busyHandler.xFunc = xBusy; - db->busyHandler.pArg = pArg; + db->busyHandler.xBusyHandler = xBusy; + db->busyHandler.pBusyArg = pArg; db->busyHandler.nBusy = 0; + db->busyHandler.bExtraFileArg = 0; db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; @@ -143560,8 +148431,10 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ - sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, + (void*)db); db->busyTimeout = ms; + db->busyHandler.bExtraFileArg = 1; }else{ sqlite3_busy_handler(db, 0, 0); } @@ -143722,11 +148595,13 @@ SQLITE_API int sqlite3_create_function_v2( #endif sqlite3_mutex_enter(db->mutex); if( xDestroy ){ - pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); + pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor)); if( !pArg ){ + sqlite3OomFault(db); xDestroy(p); goto out; } + pArg->nRef = 0; pArg->xDestroy = xDestroy; pArg->pUserData = p; } @@ -143734,7 +148609,7 @@ SQLITE_API int sqlite3_create_function_v2( if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE_OK ); xDestroy(p); - sqlite3DbFree(db, pArg); + sqlite3_free(pArg); } out: @@ -143772,6 +148647,28 @@ SQLITE_API int sqlite3_create_function16( #endif +/* +** The following is the implementation of an SQL function that always +** fails with an error message stating that the function is used in the +** wrong context. The sqlite3_overload_function() API might construct +** SQL function that use this routine so that the functions will exist +** for name resolution but are actually overloaded by the xFindFunction +** method of virtual tables. +*/ +static void sqlite3InvalidFunction( + sqlite3_context *context, /* The function calling context */ + int NotUsed, /* Number of arguments to the function */ + sqlite3_value **NotUsed2 /* Value of each argument */ +){ + const char *zName = (const char*)sqlite3_user_data(context); + char *zErr; + UNUSED_PARAMETER2(NotUsed, NotUsed2); + zErr = sqlite3_mprintf( + "unable to use function %s in the requested context", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); +} + /* ** Declare that a function has been overloaded by a virtual table. ** @@ -143789,7 +148686,8 @@ SQLITE_API int sqlite3_overload_function( const char *zName, int nArg ){ - int rc = SQLITE_OK; + int rc; + char *zCopy; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ @@ -143797,13 +148695,13 @@ SQLITE_API int sqlite3_overload_function( } #endif sqlite3_mutex_enter(db->mutex); - if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ - rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, - 0, sqlite3InvalidFunction, 0, 0, 0); - } - rc = sqlite3ApiExit(db, rc); + rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0; sqlite3_mutex_leave(db->mutex); - return rc; + if( rc ) return SQLITE_OK; + zCopy = sqlite3_mprintf(zName); + if( zCopy==0 ) return SQLITE_NOMEM; + return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8, + zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free); } #ifndef SQLITE_OMIT_TRACE @@ -144801,6 +149699,7 @@ static int openDatabase( }else{ isThreadsafe = sqlite3GlobalConfig.bFullMutex; } + if( flags & SQLITE_OPEN_PRIVATECACHE ){ flags &= ~SQLITE_OPEN_SHAREDCACHE; }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ @@ -144833,13 +149732,20 @@ static int openDatabase( /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; - if( isThreadsafe ){ + if( isThreadsafe +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS + || sqlite3GlobalConfig.bCoreMutex +#endif + ){ db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ sqlite3_free(db); db = 0; goto opendb_out; } + if( isThreadsafe==0 ){ + sqlite3MutexWarnOnContention(db->mutex); + } } sqlite3_mutex_enter(db->mutex); db->errMask = 0xff; @@ -145021,7 +149927,7 @@ static int openDatabase( } #endif -#ifdef SQLITE_ENABLE_ICU +#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3IcuInit(db); } @@ -145323,37 +150229,37 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ ** 2. Invoke sqlite3_log() to provide the source code location where ** a low-level error is first detected. */ -static int reportError(int iErr, int lineno, const char *zType){ +SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ sqlite3_log(iErr, "%s at line %d of [%.10s]", zType, lineno, 20+sqlite3_sourceid()); return iErr; } SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CORRUPT, lineno, "database corruption"); + return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); } SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_MISUSE, lineno, "misuse"); + return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse"); } SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); + return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file"); } #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ char zMsg[100]; sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CORRUPT, lineno, zMsg); + return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); } SQLITE_PRIVATE int sqlite3NomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_NOMEM, lineno, "OOM"); + return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM"); } SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); + return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); } #endif @@ -145546,10 +150452,8 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; - }else if( fd->pMethods ){ - rc = sqlite3OsFileControl(fd, op, pArg); }else{ - rc = SQLITE_NOTFOUND; + rc = sqlite3OsFileControl(fd, op, pArg); } sqlite3BtreeLeave(pBtree); } @@ -145770,24 +150674,6 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } -#ifdef SQLITE_N_KEYWORD - /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) - ** - ** If zWord is a keyword recognized by the parser, then return the - ** number of keywords. Or if zWord is not a keyword, return 0. - ** - ** This test feature is only available in the amalgamation since - ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite - ** is built using separate source files. - */ - case SQLITE_TESTCTRL_ISKEYWORD: { - const char *zWord = va_arg(ap, const char*); - int n = sqlite3Strlen30(zWord); - rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; - break; - } -#endif - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** ** If parameter onoff is non-zero, configure the wrappers so that all @@ -145881,6 +150767,22 @@ SQLITE_API int sqlite3_test_control(int op, ...){ sqlite3_mutex_leave(db->mutex); break; } + +#if defined(YYCOVERAGE) + /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out) + ** + ** This test control (only available when SQLite is compiled with + ** -DYYCOVERAGE) writes a report onto "out" that shows all + ** state/lookahead combinations in the parser state machine + ** which are never exercised. If any state is missed, make the + ** return code SQLITE_ERROR. + */ + case SQLITE_TESTCTRL_PARSER_COVERAGE: { + FILE *out = va_arg(ap, FILE*); + if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR; + break; + } +#endif /* defined(YYCOVERAGE) */ } va_end(ap); #endif /* SQLITE_UNTESTABLE */ @@ -147638,7 +152540,7 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); +SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif @@ -151348,7 +156250,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ #ifdef SQLITE_TEST if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db); + rc = sqlite3Fts3ExprInitTestInterface(db, pHash); } #endif @@ -155008,34 +159910,6 @@ SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *pDel){ /* #include */ -/* -** Function to query the hash-table of tokenizers (see README.tokenizers). -*/ -static int queryTestTokenizer( - sqlite3 *db, - const char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - /* ** Return a pointer to a buffer containing a text representation of the ** expression passed as the first argument. The buffer is obtained from @@ -155103,12 +159977,12 @@ static char *exprToString(Fts3Expr *pExpr, char *zBuf){ ** ** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); */ -static void fts3ExprTest( +static void fts3ExprTestCommon( + int bRebalance, sqlite3_context *context, int argc, sqlite3_value **argv ){ - sqlite3_tokenizer_module const *pModule = 0; sqlite3_tokenizer *pTokenizer = 0; int rc; char **azCol = 0; @@ -155118,7 +159992,9 @@ static void fts3ExprTest( int ii; Fts3Expr *pExpr; char *zBuf = 0; - sqlite3 *db = sqlite3_context_db_handle(context); + Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); + const char *zTokenizer = 0; + char *zErr = 0; if( argc<3 ){ sqlite3_result_error(context, @@ -155127,24 +160003,18 @@ static void fts3ExprTest( return; } - rc = queryTestTokenizer(db, - (const char *)sqlite3_value_text(argv[0]), &pModule); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - }else if( !pModule ){ - sqlite3_result_error(context, "No such tokenizer module", -1); - goto exprtest_out; + zTokenizer = (const char*)sqlite3_value_text(argv[0]); + rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_error(context, zErr, -1); + } + sqlite3_free(zErr); + return; } - rc = pModule->xCreate(0, 0, &pTokenizer); - assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - pTokenizer->pModule = pModule; - zExpr = (const char *)sqlite3_value_text(argv[1]); nExpr = sqlite3_value_bytes(argv[1]); nCol = argc-2; @@ -155157,7 +160027,7 @@ static void fts3ExprTest( azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); } - if( sqlite3_user_data(context) ){ + if( bRebalance ){ char *zDummy = 0; rc = sqlite3Fts3ExprParse( pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy @@ -155183,23 +160053,38 @@ static void fts3ExprTest( sqlite3Fts3ExprFree(pExpr); exprtest_out: - if( pModule && pTokenizer ){ - rc = pModule->xDestroy(pTokenizer); + if( pTokenizer ){ + rc = pTokenizer->pModule->xDestroy(pTokenizer); } sqlite3_free(azCol); } +static void fts3ExprTest( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3ExprTestCommon(0, context, argc, argv); +} +static void fts3ExprTestRebalance( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3ExprTestCommon(1, context, argc, argv); +} + /* ** Register the query expression parser test function fts3_exprtest() ** with database connection db. */ -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ +SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 + db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 ); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 + -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 ); } return rc; @@ -159384,6 +164269,7 @@ static int fts3WriteSegment( sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 2); } return rc; } @@ -159440,6 +164326,7 @@ static int fts3WriteSegdir( sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 6); } return rc; } @@ -160919,6 +165806,7 @@ static void fts3UpdateDocTotals( sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); sqlite3_step(pStmt); *pRC = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 2); sqlite3_free(a); } @@ -162107,6 +166995,7 @@ static int fts3TruncateSegment( sqlite3_bind_int(pChomp, 4, iIdx); sqlite3_step(pChomp); rc = sqlite3_reset(pChomp); + sqlite3_bind_null(pChomp, 2); } } @@ -162186,6 +167075,7 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 2); } return rc; @@ -163000,7 +167890,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ - int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ u32 *aSzDel = 0; /* Sizes of deleted documents */ int nChng = 0; /* Net change in number of documents */ @@ -163098,7 +167987,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); - isRemove = 1; } /* If this is an INSERT or UPDATE operation, insert the new record. */ @@ -163110,7 +167998,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( rc = FTS_CORRUPT_VTAB; } } - if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ + if( rc==SQLITE_OK ){ rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); } if( rc==SQLITE_OK ){ @@ -165657,14 +170545,15 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ ** ** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) ** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) -** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) +** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) ** ** The data for each node of the r-tree structure is stored in the %_node ** table. For each node that is not the root node of the r-tree, there is ** an entry in the %_parent table associating the node with its parent. ** And for each row of data in the table, there is an entry in the %_rowid ** table that maps from the entries rowid to the id of the node that it -** is stored on. +** is stored on. If the r-tree contains auxiliary columns, those are stored +** on the end of the %_rowid table. ** ** The root node of an r-tree always exists, even if the r-tree table is ** empty. The nodeno of the root node is always 1. All other nodes in the @@ -165685,7 +170574,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ ** child page. */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) +#if !defined(SQLITE_CORE) \ + || (defined(SQLITE_ENABLE_RTREE) && !defined(SQLITE_OMIT_VIRTUALTABLE)) #ifndef SQLITE_CORE /* #include "sqlite3ext.h" */ @@ -165726,6 +170616,9 @@ typedef struct RtreeSearchPoint RtreeSearchPoint; /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ #define RTREE_MAX_DIMENSIONS 5 +/* Maximum number of auxiliary columns */ +#define RTREE_MAX_AUX_COLUMN 100 + /* Size of hash table Rtree.aHash. This hash table is not expected to ** ever contain very many entries, so a fixed number of buckets is ** used. @@ -165754,12 +170647,15 @@ struct Rtree { u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ u8 nBytesPerCell; /* Bytes consumed per cell */ u8 inWrTrans; /* True if inside write transaction */ + u8 nAux; /* # of auxiliary columns in %_rowid */ int iDepth; /* Current depth of the r-tree structure */ char *zDb; /* Name of database containing r-tree table */ char *zName; /* Name of r-tree table */ u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ + u32 nNodeRef; /* Number RtreeNodes with positive nRef */ + char *zReadAuxSql; /* SQL for statement to read aux data */ /* List of nodes removed during a CondenseTree operation. List is ** linked together via the pointer normally used for hash chains - @@ -165786,6 +170682,9 @@ struct Rtree { sqlite3_stmt *pWriteParent; sqlite3_stmt *pDeleteParent; + /* Statement for writing to the "aux:" fields, if there are any */ + sqlite3_stmt *pWriteAux; + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ }; @@ -165842,7 +170741,7 @@ struct RtreeSearchPoint { ** The smallest possible node-size is (512-64)==448 bytes. And the largest ** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). ** Therefore all non-root nodes must contain at least 3 entries. Since -** 2^40 is greater than 2^64, an r-tree structure always has a depth of +** 3^40 is greater than 2^64, an r-tree structure always has a depth of ** 40 or less. */ #define RTREE_MAX_DEPTH 40 @@ -165862,6 +170761,7 @@ struct RtreeCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ u8 atEOF; /* True if at end of search */ u8 bPoint; /* True if sPoint is valid */ + u8 bAuxValid; /* True if pReadAux is valid */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ @@ -165869,6 +170769,7 @@ struct RtreeCursor { int nPoint; /* Number of slots used in aPoint[] */ int mxLevel; /* iLevel value for root of the tree */ RtreeSearchPoint *aPoint; /* Priority queue for search points */ + sqlite3_stmt *pReadAux; /* Statement to read aux-data */ RtreeSearchPoint sPoint; /* Cached next search point */ RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ @@ -166155,6 +171056,7 @@ static int writeInt64(u8 *p, i64 i){ */ static void nodeReference(RtreeNode *p){ if( p ){ + assert( p->nRef>0 ); p->nRef++; } } @@ -166222,6 +171124,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; + pRtree->nNodeRef++; pNode->pParent = pParent; pNode->isDirty = 1; nodeReference(pParent); @@ -166255,10 +171158,10 @@ static int nodeAcquire( /* Check if the requested node is already in the hash table. If so, ** increase its reference count and return it. */ - if( (pNode = nodeHashLookup(pRtree, iNode)) ){ + if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); if( pParent && !pNode->pParent ){ - nodeReference(pParent); + pParent->nRef++; pNode->pParent = pParent; } pNode->nRef++; @@ -166297,6 +171200,7 @@ static int nodeAcquire( pNode->pParent = pParent; pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; + pRtree->nNodeRef++; pNode->iNode = iNode; pNode->isDirty = 0; pNode->pNext = 0; @@ -166337,7 +171241,10 @@ static int nodeAcquire( } *ppNode = pNode; }else{ - sqlite3_free(pNode); + if( pNode ){ + pRtree->nNodeRef--; + sqlite3_free(pNode); + } *ppNode = 0; } @@ -166417,6 +171324,7 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){ sqlite3_step(p); pNode->isDirty = 0; rc = sqlite3_reset(p); + sqlite3_bind_null(p, 2); if( pNode->iNode==0 && rc==SQLITE_OK ){ pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); nodeHashInsert(pRtree, pNode); @@ -166433,8 +171341,10 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ int rc = SQLITE_OK; if( pNode ){ assert( pNode->nRef>0 ); + assert( pRtree->nNodeRef>0 ); pNode->nRef--; if( pNode->nRef==0 ){ + pRtree->nNodeRef--; if( pNode->iNode==1 ){ pRtree->iDepth = -1; } @@ -166551,8 +171461,9 @@ static void rtreeRelease(Rtree *pRtree){ pRtree->nBusy--; if( pRtree->nBusy==0 ){ pRtree->inWrTrans = 0; - pRtree->nCursor = 0; + assert( pRtree->nCursor==0 ); nodeBlobReset(pRtree); + assert( pRtree->nNodeRef==0 ); sqlite3_finalize(pRtree->pWriteNode); sqlite3_finalize(pRtree->pDeleteNode); sqlite3_finalize(pRtree->pReadRowid); @@ -166561,6 +171472,8 @@ static void rtreeRelease(Rtree *pRtree){ sqlite3_finalize(pRtree->pReadParent); sqlite3_finalize(pRtree->pWriteParent); sqlite3_finalize(pRtree->pDeleteParent); + sqlite3_finalize(pRtree->pWriteAux); + sqlite3_free(pRtree->zReadAuxSql); sqlite3_free(pRtree); } } @@ -166649,6 +171562,7 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){ RtreeCursor *pCsr = (RtreeCursor *)cur; assert( pRtree->nCursor>0 ); freeCursorConstraints(pCsr); + sqlite3_finalize(pCsr->pReadAux); sqlite3_free(pCsr->aPoint); for(ii=0; iiaNode[ii]); sqlite3_free(pCsr); @@ -167020,7 +171934,7 @@ static RtreeSearchPoint *rtreeSearchPointNew( if( iiaNode[ii]==0 ); pCur->aNode[ii] = pCur->aNode[0]; - }else{ + }else{ nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); } pCur->aNode[0] = 0; @@ -167191,6 +172105,10 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ /* Move to the next entry that matches the configured constraints. */ RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); + if( pCsr->bAuxValid ){ + pCsr->bAuxValid = 0; + sqlite3_reset(pCsr->pReadAux); + } rtreeSearchPointPop(pCsr); rc = rtreeStepToLeaf(pCsr); return rc; @@ -167225,7 +172143,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ if( p==0 ) return SQLITE_OK; if( i==0 ){ sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); - }else{ + }else if( i<=pRtree->nDim2 ){ nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ @@ -167236,7 +172154,27 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } - } + }else{ + if( !pCsr->bAuxValid ){ + if( pCsr->pReadAux==0 ){ + rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, + &pCsr->pReadAux, 0); + if( rc ) return rc; + } + sqlite3_bind_int64(pCsr->pReadAux, 1, + nodeGetRowid(pRtree, pNode, p->iCell)); + rc = sqlite3_step(pCsr->pReadAux); + if( rc==SQLITE_ROW ){ + pCsr->bAuxValid = 1; + }else{ + sqlite3_reset(pCsr->pReadAux); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + return rc; + } + } + sqlite3_result_value(ctx, + sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); + } return SQLITE_OK; } @@ -167314,14 +172252,17 @@ static int rtreeFilter( int ii; int rc = SQLITE_OK; int iCell = 0; + sqlite3_stmt *pStmt; rtreeReference(pRtree); /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ freeCursorConstraints(pCsr); sqlite3_free(pCsr->aPoint); + pStmt = pCsr->pReadAux; memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = (sqlite3_vtab*)pRtree; + pCsr->pReadAux = pStmt; pCsr->iStrategy = idxNum; if( idxNum==1 ){ @@ -167484,10 +172425,14 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ */ pIdxInfo->estimatedCost = 30.0; pIdxInfo->estimatedRows = 1; + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; return SQLITE_OK; } - if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ + if( p->usable + && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2) + || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) + ){ u8 op; switch( p->op ){ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; @@ -167654,7 +172599,7 @@ static int ChooseLeaf( ){ int rc; int ii; - RtreeNode *pNode; + RtreeNode *pNode = 0; rc = nodeAcquire(pRtree, 1, 0, &pNode); for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ @@ -168060,7 +173005,7 @@ static int SplitNode( }else{ pLeft = pNode; pRight = nodeNew(pRtree, pLeft->pParent); - nodeReference(pLeft); + pLeft->nRef++; } if( !pLeft || !pRight ){ @@ -168529,7 +173474,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ */ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ int rc2; - RtreeNode *pChild; + RtreeNode *pChild = 0; i64 iChild = nodeGetRowid(pRtree, pRoot, 0); rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); if( rc==SQLITE_OK ){ @@ -168550,6 +173495,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ rc = reinsertNodeContent(pRtree, pLeaf); } pRtree->pDeleted = pLeaf->pNext; + pRtree->nNodeRef--; sqlite3_free(pLeaf); } @@ -168646,7 +173592,7 @@ static int rtreeConstraintError(Rtree *pRtree, int iCol){ static int rtreeUpdate( sqlite3_vtab *pVtab, int nData, - sqlite3_value **azData, + sqlite3_value **aData, sqlite_int64 *pRowid ){ Rtree *pRtree = (Rtree *)pVtab; @@ -168654,6 +173600,12 @@ static int rtreeUpdate( RtreeCell cell; /* New cell to insert if nData>1 */ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ + if( pRtree->nNodeRef ){ + /* Unable to write to the btree while another cursor is reading from it, + ** since the write might do a rebalance which would disrupt the read + ** cursor. */ + return SQLITE_LOCKED_VTAB; + } rtreeReference(pRtree); assert(nData>=1); @@ -168672,8 +173624,10 @@ static int rtreeUpdate( */ if( nData>1 ){ int ii; + int nn = nData - 4; - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. + if( nn > pRtree->nDim2 ) nn = pRtree->nDim2; + /* Populate the cell.aCoord[] array. The first coordinate is aData[3]. ** ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared ** with "column" that are interpreted as table constraints. @@ -168681,13 +173635,12 @@ static int rtreeUpdate( ** This problem was discovered after years of use, so we silently ignore ** these kinds of misdeclared tables to avoid breaking any legacy. */ - assert( nData<=(pRtree->nDim2 + 3) ); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; iicell.aCoord[ii+1].f ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; @@ -168696,9 +173649,9 @@ static int rtreeUpdate( }else #endif { - for(ii=0; iicell.aCoord[ii+1].i ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; @@ -168708,10 +173661,10 @@ static int rtreeUpdate( /* If a rowid value was supplied, check if it is already present in ** the table. If so, the constraint has failed. */ - if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){ - cell.iRowid = sqlite3_value_int64(azData[2]); - if( sqlite3_value_type(azData[0])==SQLITE_NULL - || sqlite3_value_int64(azData[0])!=cell.iRowid + if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ + cell.iRowid = sqlite3_value_int64(aData[2]); + if( sqlite3_value_type(aData[0])==SQLITE_NULL + || sqlite3_value_int64(aData[0])!=cell.iRowid ){ int steprc; sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); @@ -168730,16 +173683,16 @@ static int rtreeUpdate( } } - /* If azData[0] is not an SQL NULL value, it is the rowid of a + /* If aData[0] is not an SQL NULL value, it is the rowid of a ** record to delete from the r-tree table. The following block does ** just that. */ - if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ - rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0])); + if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ + rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); } - /* If the azData[] array contains more than one element, elements - ** (azData[2]..azData[argc-1]) contain a new record to insert into + /* If the aData[] array contains more than one element, elements + ** (aData[2]..aData[argc-1]) contain a new record to insert into ** the r-tree structure. */ if( rc==SQLITE_OK && nData>1 ){ @@ -168764,6 +173717,16 @@ static int rtreeUpdate( rc = rc2; } } + if( pRtree->nAux ){ + sqlite3_stmt *pUp = pRtree->pWriteAux; + int jj; + sqlite3_bind_int64(pUp, 1, *pRowid); + for(jj=0; jjnAux; jj++){ + sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); + } + sqlite3_step(pUp); + rc = sqlite3_reset(pUp); + } } constraint: @@ -168920,18 +173883,18 @@ static int rtreeSqlInit( #define N_STATEMENT 8 static const char *azSql[N_STATEMENT] = { /* Write the xxx_node table */ - "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1", + "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)", + "DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1", /* Read and write the xxx_rowid table */ - "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1", - "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1", + "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1", + "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)", + "DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1", /* Read and write the xxx_parent table */ - "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1", - "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1" + "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1", + "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)", + "DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1" }; sqlite3_stmt **appStmt[N_STATEMENT]; int i; @@ -168939,14 +173902,25 @@ static int rtreeSqlInit( pRtree->db = db; if( isCreate ){ - char *zCreate = sqlite3_mprintf( -"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" -"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" -"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," - " parentnode INTEGER);" -"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", - zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize - ); + char *zCreate; + sqlite3_str *p = sqlite3_str_new(db); + int ii; + sqlite3_str_appendf(p, + "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno", + zDb, zPrefix); + for(ii=0; iinAux; ii++){ + sqlite3_str_appendf(p,",a%d",ii); + } + sqlite3_str_appendf(p, + ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);", + zDb, zPrefix); + sqlite3_str_appendf(p, + "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);", + zDb, zPrefix); + sqlite3_str_appendf(p, + "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))", + zDb, zPrefix, pRtree->iNodeSize); + zCreate = sqlite3_str_finish(p); if( !zCreate ){ return SQLITE_NOMEM; } @@ -168968,7 +173942,17 @@ static int rtreeSqlInit( rc = rtreeQueryStat1(db, pRtree); for(i=0; inAux==0 ){ + zFormat = azSql[i]; + }else { + /* An UPSERT is very slightly slower than REPLACE, but it is needed + ** if there are auxiliary columns */ + zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)" + "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno"; + } + zSql = sqlite3_mprintf(zFormat, zDb, zPrefix); if( zSql ){ rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, appStmt[i], 0); @@ -168977,6 +173961,32 @@ static int rtreeSqlInit( } sqlite3_free(zSql); } + if( pRtree->nAux ){ + pRtree->zReadAuxSql = sqlite3_mprintf( + "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", + zDb, zPrefix); + if( pRtree->zReadAuxSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_str *p = sqlite3_str_new(db); + int ii; + char *zSql; + sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); + for(ii=0; iinAux; ii++){ + if( ii ) sqlite3_str_append(p, ",", 1); + sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); + } + sqlite3_str_appendf(p, " WHERE rowid=?1"); + zSql = sqlite3_str_finish(p); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + &pRtree->pWriteAux, 0); + sqlite3_free(zSql); + } + } + } return rc; } @@ -169079,17 +174089,22 @@ static int rtreeInit( int nDb; /* Length of string argv[1] */ int nName; /* Length of string argv[2] */ int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); + sqlite3_str *pSql; + char *zSql; + int ii = 4; + int iErr; const char *aErrMsg[] = { 0, /* 0 */ "Wrong number of columns for an rtree table", /* 1 */ "Too few columns for an rtree table", /* 2 */ - "Too many columns for an rtree table" /* 3 */ + "Too many columns for an rtree table", /* 3 */ + "Auxiliary rtree columns must be last" /* 4 */ }; - int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; - if( aErrMsg[iErr] ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); + assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */ + if( argc>RTREE_MAX_AUX_COLUMN+3 ){ + *pzErr = sqlite3_mprintf("%s", aErrMsg[3]); return SQLITE_ERROR; } @@ -169107,53 +174122,73 @@ static int rtreeInit( pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->nDim = (u8)((argc-4)/2); - pRtree->nDim2 = pRtree->nDim*2; - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; pRtree->eCoordType = (u8)eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); /* Create/Connect to the underlying relational database schema. If ** that is successful, call sqlite3_declare_vtab() to configure ** the r-tree table schema. */ - if( rc==SQLITE_OK ){ - if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + pSql = sqlite3_str_new(db); + sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]); + for(ii=4; iinAux++; + sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); + }else if( pRtree->nAux>0 ){ + break; }else{ - char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); - char *zTmp; - int ii; - for(ii=4; zSql && iinDim2++; + sqlite3_str_appendf(pSql, ",%s", argv[ii]); } } - - if( rc==SQLITE_OK ){ - *ppVtab = (sqlite3_vtab *)pRtree; - }else{ - assert( *ppVtab==0 ); - assert( pRtree->nBusy==1 ); - rtreeRelease(pRtree); + sqlite3_str_appendf(pSql, ");"); + zSql = sqlite3_str_finish(pSql); + if( !zSql ){ + rc = SQLITE_NOMEM; + }else if( iinDim = pRtree->nDim2/2; + if( pRtree->nDim<1 ){ + iErr = 2; + }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){ + iErr = 3; + }else if( pRtree->nDim2 % 2 ){ + iErr = 1; + }else{ + iErr = 0; + } + if( iErr ){ + *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); + goto rtreeInit_fail; + } + pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; + + /* Figure out the node size to use. */ + rc = getNodeSize(db, pRtree, isCreate, pzErr); + if( rc ) goto rtreeInit_fail; + rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); + if( rc ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + goto rtreeInit_fail; + } + + *ppVtab = (sqlite3_vtab *)pRtree; + return SQLITE_OK; + +rtreeInit_fail: + if( rc==SQLITE_OK ) rc = SQLITE_ERROR; + assert( *ppVtab==0 ); + assert( pRtree->nBusy==1 ); + rtreeRelease(pRtree); return rc; } @@ -169241,6 +174276,474 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ } } +/* +** Context object passed between the various routines that make up the +** implementation of integrity-check function rtreecheck(). +*/ +typedef struct RtreeCheck RtreeCheck; +struct RtreeCheck { + sqlite3 *db; /* Database handle */ + const char *zDb; /* Database containing rtree table */ + const char *zTab; /* Name of rtree table */ + int bInt; /* True for rtree_i32 table */ + int nDim; /* Number of dimensions for this rtree tbl */ + sqlite3_stmt *pGetNode; /* Statement used to retrieve nodes */ + sqlite3_stmt *aCheckMapping[2]; /* Statements to query %_parent/%_rowid */ + int nLeaf; /* Number of leaf cells in table */ + int nNonLeaf; /* Number of non-leaf cells in table */ + int rc; /* Return code */ + char *zReport; /* Message to report */ + int nErr; /* Number of lines in zReport */ +}; + +#define RTREE_CHECK_MAX_ERROR 100 + +/* +** Reset SQL statement pStmt. If the sqlite3_reset() call returns an error, +** and RtreeCheck.rc==SQLITE_OK, set RtreeCheck.rc to the error code. +*/ +static void rtreeCheckReset(RtreeCheck *pCheck, sqlite3_stmt *pStmt){ + int rc = sqlite3_reset(pStmt); + if( pCheck->rc==SQLITE_OK ) pCheck->rc = rc; +} + +/* +** The second and subsequent arguments to this function are a format string +** and printf style arguments. This function formats the string and attempts +** to compile it as an SQL statement. +** +** If successful, a pointer to the new SQL statement is returned. Otherwise, +** NULL is returned and an error code left in RtreeCheck.rc. +*/ +static sqlite3_stmt *rtreeCheckPrepare( + RtreeCheck *pCheck, /* RtreeCheck object */ + const char *zFmt, ... /* Format string and trailing args */ +){ + va_list ap; + char *z; + sqlite3_stmt *pRet = 0; + + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + + if( pCheck->rc==SQLITE_OK ){ + if( z==0 ){ + pCheck->rc = SQLITE_NOMEM; + }else{ + pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); + } + } + + sqlite3_free(z); + va_end(ap); + return pRet; +} + +/* +** The second and subsequent arguments to this function are a printf() +** style format string and arguments. This function formats the string and +** appends it to the report being accumuated in pCheck. +*/ +static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){ + va_list ap; + va_start(ap, zFmt); + if( pCheck->rc==SQLITE_OK && pCheck->nErrrc = SQLITE_NOMEM; + }else{ + pCheck->zReport = sqlite3_mprintf("%z%s%z", + pCheck->zReport, (pCheck->zReport ? "\n" : ""), z + ); + if( pCheck->zReport==0 ){ + pCheck->rc = SQLITE_NOMEM; + } + } + pCheck->nErr++; + } + va_end(ap); +} + +/* +** This function is a no-op if there is already an error code stored +** in the RtreeCheck object indicated by the first argument. NULL is +** returned in this case. +** +** Otherwise, the contents of rtree table node iNode are loaded from +** the database and copied into a buffer obtained from sqlite3_malloc(). +** If no error occurs, a pointer to the buffer is returned and (*pnNode) +** is set to the size of the buffer in bytes. +** +** Or, if an error does occur, NULL is returned and an error code left +** in the RtreeCheck object. The final value of *pnNode is undefined in +** this case. +*/ +static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){ + u8 *pRet = 0; /* Return value */ + + assert( pCheck->rc==SQLITE_OK ); + if( pCheck->pGetNode==0 ){ + pCheck->pGetNode = rtreeCheckPrepare(pCheck, + "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", + pCheck->zDb, pCheck->zTab + ); + } + + if( pCheck->rc==SQLITE_OK ){ + sqlite3_bind_int64(pCheck->pGetNode, 1, iNode); + if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){ + int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0); + const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0); + pRet = sqlite3_malloc(nNode); + if( pRet==0 ){ + pCheck->rc = SQLITE_NOMEM; + }else{ + memcpy(pRet, pNode, nNode); + *pnNode = nNode; + } + } + rtreeCheckReset(pCheck, pCheck->pGetNode); + if( pCheck->rc==SQLITE_OK && pRet==0 ){ + rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode); + } + } + + return pRet; +} + +/* +** This function is used to check that the %_parent (if bLeaf==0) or %_rowid +** (if bLeaf==1) table contains a specified entry. The schemas of the +** two tables are: +** +** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) +** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) +** +** In both cases, this function checks that there exists an entry with +** IPK value iKey and the second column set to iVal. +** +*/ +static void rtreeCheckMapping( + RtreeCheck *pCheck, /* RtreeCheck object */ + int bLeaf, /* True for a leaf cell, false for interior */ + i64 iKey, /* Key for mapping */ + i64 iVal /* Expected value for mapping */ +){ + int rc; + sqlite3_stmt *pStmt; + const char *azSql[2] = { + "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1", + "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1" + }; + + assert( bLeaf==0 || bLeaf==1 ); + if( pCheck->aCheckMapping[bLeaf]==0 ){ + pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck, + azSql[bLeaf], pCheck->zDb, pCheck->zTab + ); + } + if( pCheck->rc!=SQLITE_OK ) return; + + pStmt = pCheck->aCheckMapping[bLeaf]; + sqlite3_bind_int64(pStmt, 1, iKey); + rc = sqlite3_step(pStmt); + if( rc==SQLITE_DONE ){ + rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table", + iKey, iVal, (bLeaf ? "%_rowid" : "%_parent") + ); + }else if( rc==SQLITE_ROW ){ + i64 ii = sqlite3_column_int64(pStmt, 0); + if( ii!=iVal ){ + rtreeCheckAppendMsg(pCheck, + "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)", + iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal + ); + } + } + rtreeCheckReset(pCheck, pStmt); +} + +/* +** Argument pCell points to an array of coordinates stored on an rtree page. +** This function checks that the coordinates are internally consistent (no +** x1>x2 conditions) and adds an error message to the RtreeCheck object +** if they are not. +** +** Additionally, if pParent is not NULL, then it is assumed to point to +** the array of coordinates on the parent page that bound the page +** containing pCell. In this case it is also verified that the two +** sets of coordinates are mutually consistent and an error message added +** to the RtreeCheck object if they are not. +*/ +static void rtreeCheckCellCoord( + RtreeCheck *pCheck, + i64 iNode, /* Node id to use in error messages */ + int iCell, /* Cell number to use in error messages */ + u8 *pCell, /* Pointer to cell coordinates */ + u8 *pParent /* Pointer to parent coordinates */ +){ + RtreeCoord c1, c2; + RtreeCoord p1, p2; + int i; + + for(i=0; inDim; i++){ + readCoord(&pCell[4*2*i], &c1); + readCoord(&pCell[4*(2*i + 1)], &c2); + + /* printf("%e, %e\n", c1.u.f, c2.u.f); */ + if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){ + rtreeCheckAppendMsg(pCheck, + "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode + ); + } + + if( pParent ){ + readCoord(&pParent[4*2*i], &p1); + readCoord(&pParent[4*(2*i + 1)], &p2); + + if( (pCheck->bInt ? c1.ibInt ? c2.i>p2.i : c2.f>p2.f) + ){ + rtreeCheckAppendMsg(pCheck, + "Dimension %d of cell %d on node %lld is corrupt relative to parent" + , i, iCell, iNode + ); + } + } + } +} + +/* +** Run rtreecheck() checks on node iNode, which is at depth iDepth within +** the r-tree structure. Argument aParent points to the array of coordinates +** that bound node iNode on the parent node. +** +** If any problems are discovered, an error message is appended to the +** report accumulated in the RtreeCheck object. +*/ +static void rtreeCheckNode( + RtreeCheck *pCheck, + int iDepth, /* Depth of iNode (0==leaf) */ + u8 *aParent, /* Buffer containing parent coords */ + i64 iNode /* Node to check */ +){ + u8 *aNode = 0; + int nNode = 0; + + assert( iNode==1 || aParent!=0 ); + assert( pCheck->nDim>0 ); + + aNode = rtreeCheckGetNode(pCheck, iNode, &nNode); + if( aNode ){ + if( nNode<4 ){ + rtreeCheckAppendMsg(pCheck, + "Node %lld is too small (%d bytes)", iNode, nNode + ); + }else{ + int nCell; /* Number of cells on page */ + int i; /* Used to iterate through cells */ + if( aParent==0 ){ + iDepth = readInt16(aNode); + if( iDepth>RTREE_MAX_DEPTH ){ + rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth); + sqlite3_free(aNode); + return; + } + } + nCell = readInt16(&aNode[2]); + if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){ + rtreeCheckAppendMsg(pCheck, + "Node %lld is too small for cell count of %d (%d bytes)", + iNode, nCell, nNode + ); + }else{ + for(i=0; inDim*2*4)]; + i64 iVal = readInt64(pCell); + rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); + + if( iDepth>0 ){ + rtreeCheckMapping(pCheck, 0, iVal, iNode); + rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); + pCheck->nNonLeaf++; + }else{ + rtreeCheckMapping(pCheck, 1, iVal, iNode); + pCheck->nLeaf++; + } + } + } + } + sqlite3_free(aNode); + } +} + +/* +** The second argument to this function must be either "_rowid" or +** "_parent". This function checks that the number of entries in the +** %_rowid or %_parent table is exactly nExpect. If not, it adds +** an error message to the report in the RtreeCheck object indicated +** by the first argument. +*/ +static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){ + if( pCheck->rc==SQLITE_OK ){ + sqlite3_stmt *pCount; + pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'", + pCheck->zDb, pCheck->zTab, zTbl + ); + if( pCount ){ + if( sqlite3_step(pCount)==SQLITE_ROW ){ + i64 nActual = sqlite3_column_int64(pCount, 0); + if( nActual!=nExpect ){ + rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table" + " - expected %lld, actual %lld" , zTbl, nExpect, nActual + ); + } + } + pCheck->rc = sqlite3_finalize(pCount); + } + } +} + +/* +** This function does the bulk of the work for the rtree integrity-check. +** It is called by rtreecheck(), which is the SQL function implementation. +*/ +static int rtreeCheckTable( + sqlite3 *db, /* Database handle to access db through */ + const char *zDb, /* Name of db ("main", "temp" etc.) */ + const char *zTab, /* Name of rtree table to check */ + char **pzReport /* OUT: sqlite3_malloc'd report text */ +){ + RtreeCheck check; /* Common context for various routines */ + sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ + int bEnd = 0; /* True if transaction should be closed */ + int nAux = 0; /* Number of extra columns. */ + + /* Initialize the context object */ + memset(&check, 0, sizeof(check)); + check.db = db; + check.zDb = zDb; + check.zTab = zTab; + + /* If there is not already an open transaction, open one now. This is + ** to ensure that the queries run as part of this integrity-check operate + ** on a consistent snapshot. */ + if( sqlite3_get_autocommit(db) ){ + check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); + bEnd = 1; + } + + /* Find the number of auxiliary columns */ + if( check.rc==SQLITE_OK ){ + pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); + if( pStmt ){ + nAux = sqlite3_column_count(pStmt) - 2; + sqlite3_finalize(pStmt); + } + check.rc = SQLITE_OK; + } + + /* Find number of dimensions in the rtree table. */ + pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab); + if( pStmt ){ + int rc; + check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2; + if( check.nDim<1 ){ + rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree"); + }else if( SQLITE_ROW==sqlite3_step(pStmt) ){ + check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER); + } + rc = sqlite3_finalize(pStmt); + if( rc!=SQLITE_CORRUPT ) check.rc = rc; + } + + /* Do the actual integrity-check */ + if( check.nDim>=1 ){ + if( check.rc==SQLITE_OK ){ + rtreeCheckNode(&check, 0, 0, 1); + } + rtreeCheckCount(&check, "_rowid", check.nLeaf); + rtreeCheckCount(&check, "_parent", check.nNonLeaf); + } + + /* Finalize SQL statements used by the integrity-check */ + sqlite3_finalize(check.pGetNode); + sqlite3_finalize(check.aCheckMapping[0]); + sqlite3_finalize(check.aCheckMapping[1]); + + /* If one was opened, close the transaction */ + if( bEnd ){ + int rc = sqlite3_exec(db, "END", 0, 0, 0); + if( check.rc==SQLITE_OK ) check.rc = rc; + } + *pzReport = check.zReport; + return check.rc; +} + +/* +** Usage: +** +** rtreecheck(); +** rtreecheck(, ); +** +** Invoking this SQL function runs an integrity-check on the named rtree +** table. The integrity-check verifies the following: +** +** 1. For each cell in the r-tree structure (%_node table), that: +** +** a) for each dimension, (coord1 <= coord2). +** +** b) unless the cell is on the root node, that the cell is bounded +** by the parent cell on the parent node. +** +** c) for leaf nodes, that there is an entry in the %_rowid +** table corresponding to the cell's rowid value that +** points to the correct node. +** +** d) for cells on non-leaf nodes, that there is an entry in the +** %_parent table mapping from the cell's child node to the +** node that it resides on. +** +** 2. That there are the same number of entries in the %_rowid table +** as there are leaf cells in the r-tree structure, and that there +** is a leaf cell that corresponds to each entry in the %_rowid table. +** +** 3. That there are the same number of entries in the %_parent table +** as there are non-leaf cells in the r-tree structure, and that +** there is a non-leaf cell that corresponds to each entry in the +** %_parent table. +*/ +static void rtreecheck( + sqlite3_context *ctx, + int nArg, + sqlite3_value **apArg +){ + if( nArg!=1 && nArg!=2 ){ + sqlite3_result_error(ctx, + "wrong number of arguments to function rtreecheck()", -1 + ); + }else{ + int rc; + char *zReport = 0; + const char *zDb = (const char*)sqlite3_value_text(apArg[0]); + const char *zTab; + if( nArg==1 ){ + zTab = zDb; + zDb = "main"; + }else{ + zTab = (const char*)sqlite3_value_text(apArg[1]); + } + rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); + if( rc==SQLITE_OK ){ + sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_error_code(ctx, rc); + } + sqlite3_free(zReport); + } +} + + /* ** Register the r-tree module with database handle db. This creates the ** virtual table module "rtree" and the debugging/analysis scalar @@ -169254,6 +174757,9 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){ if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0); + } if( rc==SQLITE_OK ){ #ifdef SQLITE_RTREE_INT_ONLY void *c = (void *)RTREE_COORD_INT32; @@ -169440,7 +174946,9 @@ SQLITE_API int sqlite3_rtree_init( ** provide case-independent matching. */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) +#if !defined(SQLITE_CORE) \ + || defined(SQLITE_ENABLE_ICU) \ + || defined(SQLITE_ENABLE_ICU_COLLATIONS) /* Include ICU headers */ #include @@ -169457,6 +174965,26 @@ SQLITE_API int sqlite3_rtree_init( /* #include "sqlite3.h" */ #endif +/* +** This function is called when an ICU function called from within +** the implementation of an SQL scalar function returns an error. +** +** The scalar function context passed as the first argument is +** loaded with an error message based on the following two args. +*/ +static void icuFunctionError( + sqlite3_context *pCtx, /* SQLite scalar function context */ + const char *zName, /* Name of ICU function that failed */ + UErrorCode e /* Error code returned by ICU function */ +){ + char zBuf[128]; + sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); + zBuf[127] = '\0'; + sqlite3_result_error(pCtx, zBuf, -1); +} + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) + /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. @@ -169636,24 +175164,6 @@ static void icuLikeFunc( } } -/* -** This function is called when an ICU function called from within -** the implementation of an SQL scalar function returns an error. -** -** The scalar function context passed as the first argument is -** loaded with an error message based on the following two args. -*/ -static void icuFunctionError( - sqlite3_context *pCtx, /* SQLite scalar function context */ - const char *zName, /* Name of ICU function that failed */ - UErrorCode e /* Error code returned by ICU function */ -){ - char zBuf[128]; - sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); - zBuf[127] = '\0'; - sqlite3_result_error(pCtx, zBuf, -1); -} - /* ** Function to delete compiled regexp objects. Registered as ** a destructor function with sqlite3_set_auxdata(). @@ -169819,6 +175329,8 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ assert( 0 ); /* Unreachable */ } +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ + /* ** Collation sequence destructor function. The pCtx argument points to ** a UCollator structure previously allocated using ucol_open(). @@ -169913,6 +175425,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } scalars[] = { {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation}, +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, @@ -169924,10 +175437,10 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ }; int rc = SQLITE_OK; int i; - for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){ const struct IcuScalar *p = &scalars[i]; @@ -170984,6 +176497,10 @@ SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); ** ** RBU_STATE_OALSZ: ** Valid if STAGE==1. The size in bytes of the *-oal file. +** +** RBU_STATE_DATATBL: +** Only valid if STAGE==1. The RBU database name of the table +** currently being read. */ #define RBU_STATE_STAGE 1 #define RBU_STATE_TBL 2 @@ -170994,6 +176511,7 @@ SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); #define RBU_STATE_COOKIE 7 #define RBU_STATE_OALSZ 8 #define RBU_STATE_PHASEONESTEP 9 +#define RBU_STATE_DATATBL 10 #define RBU_STAGE_OAL 1 #define RBU_STAGE_MOVE 2 @@ -171036,6 +176554,7 @@ typedef sqlite3_int64 i64; struct RbuState { int eStage; char *zTbl; + char *zDataTbl; char *zIdx; i64 iWalCksum; int nRow; @@ -172637,7 +178156,7 @@ static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, + zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, iCid, pIter->azTblType[iCid], zCollate ); zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); @@ -172698,7 +178217,7 @@ static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", + zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, (pIter->abNotNull[iCol] ? " NOT NULL" : "") ); @@ -173099,6 +178618,7 @@ static sqlite3 *rbuOpenDbhandle( static void rbuFreeState(RbuState *p){ if( p ){ sqlite3_free(p->zTbl); + sqlite3_free(p->zDataTbl); sqlite3_free(p->zIdx); sqlite3_free(p); } @@ -173169,6 +178689,10 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); break; + case RBU_STATE_DATATBL: + pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); + break; + default: rc = SQLITE_CORRUPT; break; @@ -173943,7 +179467,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ "(%d, %lld), " "(%d, %lld), " "(%d, %lld), " - "(%d, %lld) ", + "(%d, %lld), " + "(%d, %Q) ", p->zStateDb, RBU_STATE_STAGE, eStage, RBU_STATE_TBL, p->objiter.zTbl, @@ -173953,7 +179478,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ RBU_STATE_CKPT, p->iWalCksum, RBU_STATE_COOKIE, (i64)pFd->iCookie, RBU_STATE_OALSZ, p->iOalSz, - RBU_STATE_PHASEONESTEP, p->nPhaseOneStep + RBU_STATE_PHASEONESTEP, p->nPhaseOneStep, + RBU_STATE_DATATBL, p->objiter.zDataTbl ) ); assert( pInsert==0 || rc==SQLITE_OK ); @@ -174209,7 +179735,8 @@ static void rbuSetupOal(sqlite3rbu *p, RbuState *pState){ while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup || rbuStrCompare(pIter->zIdx, pState->zIdx) - || rbuStrCompare(pIter->zTbl, pState->zTbl) + || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl)) + || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl)) )){ rc = rbuObjIterNext(p, pIter); } @@ -176132,7 +181659,7 @@ static void statSizeAndOffset(StatCursor *pCsr){ */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; - if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ pCsr->iOffset = x[0]; pCsr->szPage = (int)x[1]; } @@ -176458,17 +181985,24 @@ struct DbpageCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ int pgno; /* Current page number */ int mxPgno; /* Last page to visit on this scan */ + Pager *pPager; /* Pager being read/written */ + DbPage *pPage1; /* Page 1 of the database */ + int iDb; /* Index of database to analyze */ + int szPage; /* Size of each page in bytes */ }; struct DbpageTable { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* The database */ - Pager *pPager; /* Pager being read/written */ - int iDb; /* Index of database to analyze */ - int szPage; /* Size of each page in bytes */ - int nPage; /* Number of pages in the file */ }; +/* Columns */ +#define DBPAGE_COLUMN_PGNO 0 +#define DBPAGE_COLUMN_DATA 1 +#define DBPAGE_COLUMN_SCHEMA 2 + + + /* ** Connect to or create a dbpagevfs virtual table. */ @@ -176481,19 +182015,7 @@ static int dbpageConnect( ){ DbpageTable *pTab = 0; int rc = SQLITE_OK; - int iDb; - if( argc>=4 ){ - Token nm; - sqlite3TokenInit(&nm, (char*)argv[3]); - iDb = sqlite3FindDb(db, &nm); - if( iDb<0 ){ - *pzErr = sqlite3_mprintf("no such schema: %s", argv[3]); - return SQLITE_ERROR; - } - }else{ - iDb = 0; - } rc = sqlite3_declare_vtab(db, "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)"); if( rc==SQLITE_OK ){ @@ -176503,11 +182025,8 @@ static int dbpageConnect( assert( rc==SQLITE_OK || pTab==0 ); if( rc==SQLITE_OK ){ - Btree *pBt = db->aDb[iDb].pBt; memset(pTab, 0, sizeof(DbpageTable)); pTab->db = db; - pTab->iDb = iDb; - pTab->pPager = pBt ? sqlite3BtreePager(pBt) : 0; } *ppVtab = (sqlite3_vtab*)pTab; @@ -176525,24 +182044,55 @@ static int dbpageDisconnect(sqlite3_vtab *pVtab){ /* ** idxNum: ** -** 0 full table scan -** 1 pgno=?1 +** 0 schema=main, full table scan +** 1 schema=main, pgno=?1 +** 2 schema=?1, full table scan +** 3 schema=?1, pgno=?2 */ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; - pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ + int iPlan = 0; + + /* If there is a schema= constraint, it must be honored. Report a + ** ridiculously large estimated cost if the schema= constraint is + ** unavailable + */ + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; + if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; + if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + if( !p->usable ){ + /* No solution. Use the default SQLITE_BIG_DBL cost */ + pIdxInfo->estimatedRows = 0x7fffffff; + return SQLITE_OK; + } + iPlan = 2; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + break; + } + + /* If we reach this point, it means that either there is no schema= + ** constraint (in which case we use the "main" schema) or else the + ** schema constraint was accepted. Lower the estimated cost accordingly + */ + pIdxInfo->estimatedCost = 1.0e6; + + /* Check for constraints against pgno */ for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ pIdxInfo->estimatedRows = 1; pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; pIdxInfo->estimatedCost = 1.0; - pIdxInfo->idxNum = 1; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1; pIdxInfo->aConstraintUsage[i].omit = 1; + iPlan |= 1; break; } } + pIdxInfo->idxNum = iPlan; + if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn<=0 && pIdxInfo->aOrderBy[0].desc==0 @@ -176576,6 +182126,7 @@ static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ */ static int dbpageClose(sqlite3_vtab_cursor *pCursor){ DbpageCursor *pCsr = (DbpageCursor *)pCursor; + if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); sqlite3_free(pCsr); return SQLITE_OK; } @@ -176595,6 +182146,16 @@ static int dbpageEof(sqlite3_vtab_cursor *pCursor){ return pCsr->pgno > pCsr->mxPgno; } +/* +** idxNum: +** +** 0 schema=main, full table scan +** 1 schema=main, pgno=?1 +** 2 schema=?1, full table scan +** 3 schema=?1, pgno=?2 +** +** idxStr is not used +*/ static int dbpageFilter( sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, @@ -176602,23 +182163,42 @@ static int dbpageFilter( ){ DbpageCursor *pCsr = (DbpageCursor *)pCursor; DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; - int rc = SQLITE_OK; - Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; + int rc; + sqlite3 *db = pTab->db; + Btree *pBt; - pTab->szPage = sqlite3BtreeGetPageSize(pBt); - pTab->nPage = sqlite3BtreeLastPage(pBt); - if( idxNum==1 ){ - pCsr->pgno = sqlite3_value_int(argv[0]); - if( pCsr->pgno<1 || pCsr->pgno>pTab->nPage ){ + /* Default setting is no rows of result */ + pCsr->pgno = 1; + pCsr->mxPgno = 0; + + if( idxNum & 2 ){ + const char *zSchema; + assert( argc>=1 ); + zSchema = (const char*)sqlite3_value_text(argv[0]); + pCsr->iDb = sqlite3FindDbName(db, zSchema); + if( pCsr->iDb<0 ) return SQLITE_OK; + }else{ + pCsr->iDb = 0; + } + pBt = db->aDb[pCsr->iDb].pBt; + if( pBt==0 ) return SQLITE_OK; + pCsr->pPager = sqlite3BtreePager(pBt); + pCsr->szPage = sqlite3BtreeGetPageSize(pBt); + pCsr->mxPgno = sqlite3BtreeLastPage(pBt); + if( idxNum & 1 ){ + assert( argc>(idxNum>>1) ); + pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]); + if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){ pCsr->pgno = 1; pCsr->mxPgno = 0; }else{ pCsr->mxPgno = pCsr->pgno; } }else{ - pCsr->pgno = 1; - pCsr->mxPgno = pTab->nPage; + assert( pCsr->pgno==1 ); } + if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); + rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); return rc; } @@ -176628,7 +182208,6 @@ static int dbpageColumn( int i ){ DbpageCursor *pCsr = (DbpageCursor *)pCursor; - DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; int rc = SQLITE_OK; switch( i ){ case 0: { /* pgno */ @@ -176637,9 +182216,9 @@ static int dbpageColumn( } case 1: { /* data */ DbPage *pDbPage = 0; - rc = sqlite3PagerGet(pTab->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); + rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); if( rc==SQLITE_OK ){ - sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pTab->szPage, + sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage, SQLITE_TRANSIENT); } sqlite3PagerUnref(pDbPage); @@ -176647,7 +182226,7 @@ static int dbpageColumn( } default: { /* schema */ sqlite3 *db = sqlite3_context_db_handle(ctx); - sqlite3_result_text(ctx, db->aDb[pTab->iDb].zDbSName, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC); break; } } @@ -176667,37 +182246,51 @@ static int dbpageUpdate( sqlite_int64 *pRowid ){ DbpageTable *pTab = (DbpageTable *)pVtab; - int pgno; + Pgno pgno; DbPage *pDbPage = 0; int rc = SQLITE_OK; char *zErr = 0; + const char *zSchema; + int iDb; + Btree *pBt; + Pager *pPager; + int szPage; if( argc==1 ){ zErr = "cannot delete"; goto update_fail; } pgno = sqlite3_value_int(argv[0]); - if( pgno<1 || pgno>pTab->nPage ){ - zErr = "bad page number"; - goto update_fail; - } - if( sqlite3_value_int(argv[1])!=pgno ){ + if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ zErr = "cannot insert"; goto update_fail; } + zSchema = (const char*)sqlite3_value_text(argv[4]); + iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1; + if( iDb<0 ){ + zErr = "no such schema"; + goto update_fail; + } + pBt = pTab->db->aDb[iDb].pBt; + if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){ + zErr = "bad page number"; + goto update_fail; + } + szPage = sqlite3BtreeGetPageSize(pBt); if( sqlite3_value_type(argv[3])!=SQLITE_BLOB - || sqlite3_value_bytes(argv[3])!=pTab->szPage + || sqlite3_value_bytes(argv[3])!=szPage ){ zErr = "bad page value"; goto update_fail; } - rc = sqlite3PagerGet(pTab->pPager, pgno, (DbPage**)&pDbPage, 0); + pPager = sqlite3BtreePager(pBt); + rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ memcpy(sqlite3PagerGetData(pDbPage), sqlite3_value_blob(argv[3]), - pTab->szPage); + szPage); } } sqlite3PagerUnref(pDbPage); @@ -176709,6 +182302,22 @@ update_fail: return SQLITE_ERROR; } +/* Since we do not know in advance which database files will be +** written by the sqlite_dbpage virtual table, start a write transaction +** on them all. +*/ +static int dbpageBegin(sqlite3_vtab *pVtab){ + DbpageTable *pTab = (DbpageTable *)pVtab; + sqlite3 *db = pTab->db; + int i; + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ) sqlite3BtreeBeginTrans(pBt, 1); + } + return SQLITE_OK; +} + + /* ** Invoke this routine to register the "dbpage" virtual table module */ @@ -176728,7 +182337,7 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ dbpageColumn, /* xColumn - read data */ dbpageRowid, /* xRowid - read data */ dbpageUpdate, /* xUpdate */ - 0, /* xBegin */ + dbpageBegin, /* xBegin */ 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ @@ -176794,6 +182403,7 @@ struct sqlite3_session { int rc; /* Non-zero if an error has occurred */ void *pFilterCtx; /* First argument to pass to xTableFilter */ int (*xTableFilter)(void *pCtx, const char *zTab); + sqlite3_value *pZeroBlob; /* Value containing X'' */ sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ SessionHook hook; /* APIs to grab new and old data with */ @@ -176815,7 +182425,7 @@ struct SessionBuffer { ** sqlite3changeset_start_strm()). */ struct SessionInput { - int bNoDiscard; /* If true, discard no data */ + int bNoDiscard; /* If true, do not discard in InputBuffer() */ int iCurrent; /* Offset in aData[] of current change */ int iNext; /* Offset in aData[] of next change */ u8 *aData; /* Pointer to buffer containing changeset */ @@ -176861,6 +182471,7 @@ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ int nCol; /* Number of columns in table zName */ + int bStat1; /* True if this is sqlite_stat1 */ const char **azCol; /* Column names */ u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ @@ -176978,8 +182589,8 @@ struct SessionTable { ** statement. ** ** For a DELETE change, all fields within the record except those associated -** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields -** contain the values identifying the row to delete. +** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the +** values identifying the row to delete. ** ** For an UPDATE change, all fields except those associated with PRIMARY KEY ** columns and columns that are modified by the UPDATE are set to "undefined". @@ -177244,6 +182855,7 @@ static int sessionPreupdateHash( h = sessionHashAppendBlob(h, n, z); }else{ assert( eType==SQLITE_NULL ); + assert( pTab->bStat1==0 || i!=1 ); *pbNullPK = 1; } } @@ -177261,7 +182873,7 @@ static int sessionPreupdateHash( static int sessionSerialLen(u8 *a){ int e = *a; int n; - if( e==0 ) return 1; + if( e==0 || e==0xFF ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; return sessionVarintGet(&a[1], &n) + 1 + n; @@ -177341,7 +182953,7 @@ static int sessionChangeEqual( int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); - if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ + if( n1!=n2 || memcmp(a1, a2, n1) ){ return 0; } a1 += n1; @@ -177584,9 +183196,8 @@ static int sessionPreupdateEqual( }else{ z = sqlite3_value_blob(pVal); } - if( memcmp(a, z, n) ) return 0; + if( n>0 && memcmp(a, z, n) ) return 0; a += n; - break; } } } @@ -177642,9 +183253,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){ /* ** This function queries the database for the names of the columns of table -** zThis, in schema zDb. It is expected that the table has nCol columns. If -** not, SQLITE_SCHEMA is returned and none of the output variables are -** populated. +** zThis, in schema zDb. ** ** Otherwise, if they are not NULL, variable *pnCol is set to the number ** of columns in the database table and variable *pzTab is set to point to a @@ -177665,9 +183274,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){ ** *pabPK = {1, 0, 0, 1} ** ** All returned buffers are part of the same single allocation, which must -** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then -** pointer *pazCol should be freed to release all memory. Otherwise, pointer -** *pabPK. It is illegal for both pazCol and pabPK to be NULL. +** be freed using sqlite3_free() by the caller */ static int sessionTableInfo( sqlite3 *db, /* Database connection */ @@ -177692,7 +183299,23 @@ static int sessionTableInfo( assert( pazCol && pabPK ); nThis = sqlite3Strlen30(zThis); - zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){ + rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0); + if( rc==SQLITE_OK ){ + /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */ + zPragma = sqlite3_mprintf( + "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL " + "SELECT 1, 'idx', '', 0, '', 2 UNION ALL " + "SELECT 2, 'stat', '', 0, '', 0" + ); + }else if( rc==SQLITE_ERROR ){ + zPragma = sqlite3_mprintf(""); + }else{ + return rc; + } + }else{ + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + } if( !zPragma ) return SQLITE_NOMEM; rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); @@ -177784,11 +183407,55 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ break; } } + if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){ + pTab->bStat1 = 1; + } } } return (pSession->rc || pTab->abPK==0); } +/* +** Versions of the four methods in object SessionHook for use with the +** sqlite_stat1 table. The purpose of this is to substitute a zero-length +** blob each time a NULL value is read from the "idx" column of the +** sqlite_stat1 table. +*/ +typedef struct SessionStat1Ctx SessionStat1Ctx; +struct SessionStat1Ctx { + SessionHook hook; + sqlite3_session *pSession; +}; +static int sessionStat1Old(void *pCtx, int iCol, sqlite3_value **ppVal){ + SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; + sqlite3_value *pVal = 0; + int rc = p->hook.xOld(p->hook.pCtx, iCol, &pVal); + if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ + pVal = p->pSession->pZeroBlob; + } + *ppVal = pVal; + return rc; +} +static int sessionStat1New(void *pCtx, int iCol, sqlite3_value **ppVal){ + SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; + sqlite3_value *pVal = 0; + int rc = p->hook.xNew(p->hook.pCtx, iCol, &pVal); + if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ + pVal = p->pSession->pZeroBlob; + } + *ppVal = pVal; + return rc; +} +static int sessionStat1Count(void *pCtx){ + SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; + return p->hook.xCount(p->hook.pCtx); +} +static int sessionStat1Depth(void *pCtx){ + SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; + return p->hook.xDepth(p->hook.pCtx); +} + + /* ** This function is only called from with a pre-update-hook reporting a ** change on table pTab (attached to session pSession). The type of change @@ -177805,6 +183472,7 @@ static void sessionPreupdateOneChange( int iHash; int bNull = 0; int rc = SQLITE_OK; + SessionStat1Ctx stat1 = {0}; if( pSession->rc ) return; @@ -177824,6 +183492,25 @@ static void sessionPreupdateOneChange( return; } + if( pTab->bStat1 ){ + stat1.hook = pSession->hook; + stat1.pSession = pSession; + pSession->hook.pCtx = (void*)&stat1; + pSession->hook.xNew = sessionStat1New; + pSession->hook.xOld = sessionStat1Old; + pSession->hook.xCount = sessionStat1Count; + pSession->hook.xDepth = sessionStat1Depth; + if( pSession->pZeroBlob==0 ){ + sqlite3_value *p = sqlite3ValueNew(0); + if( p==0 ){ + rc = SQLITE_NOMEM; + goto error_out; + } + sqlite3ValueSetStr(p, 0, "", 0, SQLITE_STATIC); + pSession->pZeroBlob = p; + } + } + /* Calculate the hash-key for this change. If the primary key of the row ** includes a NULL value, exit early. Such changes are ignored by the ** session module. */ @@ -177913,6 +183600,9 @@ static void sessionPreupdateOneChange( /* If an error has occurred, mark the session object as failed. */ error_out: + if( pTab->bStat1 ){ + pSession->hook = stat1.hook; + } if( rc!=SQLITE_OK ){ pSession->rc = rc; } @@ -178249,7 +183939,6 @@ SQLITE_API int sqlite3session_diff( if( abPK[i] ) bHasPk = 1; } } - } sqlite3_free((char*)azCol); if( bMismatch ){ @@ -178375,6 +184064,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){ } } sqlite3_mutex_leave(sqlite3_db_mutex(db)); + sqlite3ValueFree(pSession->pZeroBlob); /* Delete all attached table objects. And the contents of their ** associated hash-tables. */ @@ -178842,28 +184532,42 @@ static int sessionSelectStmt( sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ ){ int rc = SQLITE_OK; - int i; - const char *zSep = ""; - SessionBuffer buf = {0, 0, 0}; + char *zSql = 0; + int nSql = -1; - sessionAppendStr(&buf, "SELECT * FROM ", &rc); - sessionAppendIdent(&buf, zDb, &rc); - sessionAppendStr(&buf, ".", &rc); - sessionAppendIdent(&buf, zTab, &rc); - sessionAppendStr(&buf, " WHERE ", &rc); - for(i=0; ibEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ @@ -179374,13 +185078,16 @@ static int sessionReadRecord( if( abPK && abPK[i]==0 ) continue; rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - eType = pIn->aData[pIn->iNext++]; - } - - assert( apOut[i]==0 ); - if( eType ){ - apOut[i] = sqlite3ValueNew(0); - if( !apOut[i] ) rc = SQLITE_NOMEM; + if( pIn->iNext>=pIn->nData ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + eType = pIn->aData[pIn->iNext++]; + assert( apOut[i]==0 ); + if( eType ){ + apOut[i] = sqlite3ValueNew(0); + if( !apOut[i] ) rc = SQLITE_NOMEM; + } + } } if( rc==SQLITE_OK ){ @@ -179390,10 +185097,14 @@ static int sessionReadRecord( pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( rc==SQLITE_OK ){ - u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); - rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + pIn->iNext += nByte; + } } - pIn->iNext += nByte; } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ sqlite3_int64 v = sessionGetI64(aVal); @@ -179433,8 +185144,19 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); - rc = sessionInputBuffer(pIn, nRead+nCol+100); - nRead += nCol; + /* The hard upper limit for the number of columns in an SQLite + ** database table is, according to sqliteLimit.h, 32676. So + ** consider any table-header that purports to have more than 65536 + ** columns to be corrupt. This is convenient because otherwise, + ** if the (nCol>65536) condition below were omitted, a sufficiently + ** large value for nCol may cause nRead to wrap around and become + ** negative. Leading to a crash. */ + if( nCol<0 || nCol>65536 ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = sessionInputBuffer(pIn, nRead+nCol+100); + nRead += nCol; + } } while( rc==SQLITE_OK ){ @@ -179511,11 +185233,15 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ int nByte; int nVarint; nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); - nCopy -= nVarint; - p->in.iNext += nVarint; - nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; - p->tblhdr.nBuf = 0; - sessionBufferGrow(&p->tblhdr, nByte, &rc); + if( p->nCol>0 ){ + nCopy -= nVarint; + p->in.iNext += nVarint; + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; + p->tblhdr.nBuf = 0; + sessionBufferGrow(&p->tblhdr, nByte, &rc); + }else{ + rc = SQLITE_CORRUPT_BKPT; + } } if( rc==SQLITE_OK ){ @@ -179550,7 +185276,8 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ - int *pnRec /* If non-NULL, store size of record here */ + int *pnRec, /* If non-NULL, store size of record here */ + int *pbNew /* If non-NULL, true if new table */ ){ int i; u8 op; @@ -179585,6 +185312,7 @@ static int sessionChangesetNext( op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ + if( pbNew ) *pbNew = 1; p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; @@ -179593,6 +185321,13 @@ static int sessionChangesetNext( op = p->in.aData[p->in.iNext++]; } + if( p->zTab==0 ){ + /* The first record in the changeset is not a table header. Must be a + ** corrupt changeset. */ + assert( p->in.iNext==1 ); + return (p->rc = SQLITE_CORRUPT_BKPT); + } + p->op = op; p->bIndirect = p->in.aData[p->in.iNext++]; if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ @@ -179635,9 +185370,9 @@ static int sessionChangesetNext( ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; inCol; i++){ assert( p->apValue[i]==0 ); - assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); if( p->abPK[i] ){ p->apValue[i] = p->apValue[i+p->nCol]; + if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } @@ -179656,7 +185391,7 @@ static int sessionChangesetNext( ** callback by changeset_apply(). */ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ - return sessionChangesetNext(p, 0, 0); + return sessionChangesetNext(p, 0, 0, 0); } /* @@ -180032,9 +185767,11 @@ struct SessionApplyCtx { int nCol; /* Size of azCol[] and abPK[] arrays */ const char **azCol; /* Array of column names */ u8 *abPK; /* Boolean array - true if column is in PK */ - + int bStat1; /* True if table is sqlite_stat1 */ int bDeferConstraints; /* True to defer constraints */ SessionBuffer constraints; /* Deferred constraints are stored here */ + SessionBuffer rebase; /* Rebase information (if any) here */ + int bRebaseStarted; /* If table header is already in rebase */ }; /* @@ -180202,6 +185939,7 @@ static int sessionUpdateRow( return rc; } + /* ** Formulate and prepare an SQL statement to query table zTab by primary ** key. Assuming the following table structure: @@ -180263,6 +186001,46 @@ static int sessionInsertRow( return rc; } +static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ + return sqlite3_prepare_v2(db, zSql, -1, pp, 0); +} + +/* +** Prepare statements for applying changes to the sqlite_stat1 table. +** These are similar to those created by sessionSelectRow(), +** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for +** other tables. +*/ +static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ + int rc = sessionSelectRow(db, "sqlite_stat1", p); + if( rc==SQLITE_OK ){ + rc = sessionPrepare(db, &p->pInsert, + "INSERT INTO main.sqlite_stat1 VALUES(?1, " + "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " + "?3)" + ); + } + if( rc==SQLITE_OK ){ + rc = sessionPrepare(db, &p->pUpdate, + "UPDATE main.sqlite_stat1 SET " + "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, " + "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, " + "stat = CASE WHEN ?8 THEN ?9 ELSE stat END " + "WHERE tbl=?1 AND idx IS " + "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END " + "AND (?10 OR ?8=0 OR stat IS ?7)" + ); + } + if( rc==SQLITE_OK ){ + rc = sessionPrepare(db, &p->pDelete, + "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " + "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " + "AND (?4 OR stat IS ?3)" + ); + } + return rc; +} + /* ** A wrapper around sqlite3_bind_value() that detects an extra problem. ** See comments in the body of this function for details. @@ -180320,7 +186098,13 @@ static int sessionBindRow( if( !abPK || abPK[i] ){ sqlite3_value *pVal; (void)xValue(pIter, i, &pVal); - rc = sessionBindValue(pStmt, i+1, pVal); + if( pVal==0 ){ + /* The value in the changeset was "undefined". This indicates a + ** corrupt changeset blob. */ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = sessionBindValue(pStmt, i+1, pVal); + } } } return rc; @@ -180368,6 +186152,54 @@ static int sessionSeekToRow( return rc; } +/* +** This function is called from within sqlite3changset_apply_v2() when +** a conflict is encountered and resolved using conflict resolution +** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. +** It adds a conflict resolution record to the buffer in +** SessionApplyCtx.rebase, which will eventually be returned to the caller +** of apply_v2() as the "rebase" buffer. +** +** Return SQLITE_OK if successful, or an SQLite error code otherwise. +*/ +static int sessionRebaseAdd( + SessionApplyCtx *p, /* Apply context */ + int eType, /* Conflict resolution (OMIT or REPLACE) */ + sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ +){ + int rc = SQLITE_OK; + int i; + int eOp = pIter->op; + if( p->bRebaseStarted==0 ){ + /* Append a table-header to the rebase buffer */ + const char *zTab = pIter->zTab; + sessionAppendByte(&p->rebase, 'T', &rc); + sessionAppendVarint(&p->rebase, p->nCol, &rc); + sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); + sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); + p->bRebaseStarted = 1; + } + + assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); + assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); + + sessionAppendByte(&p->rebase, + (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc + ); + sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); + for(i=0; inCol; i++){ + sqlite3_value *pVal = 0; + if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ + sqlite3changeset_old(pIter, i, &pVal); + }else{ + sqlite3changeset_new(pIter, i, &pVal); + } + sessionAppendValue(&p->rebase, pVal, &rc); + } + + return rc; +} + /* ** Invoke the conflict handler for the change that the changeset iterator ** currently points to. @@ -180443,7 +186275,7 @@ static int sessionConflictHandler( u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); - res = SQLITE_CHANGESET_OMIT; + return SQLITE_OK; }else{ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); @@ -180469,6 +186301,9 @@ static int sessionConflictHandler( rc = SQLITE_MISUSE; break; } + if( rc==SQLITE_OK ){ + rc = sessionRebaseAdd(p, res, pIter); + } } return rc; @@ -180593,11 +186428,25 @@ static int sessionApplyOneOp( }else{ assert( op==SQLITE_INSERT ); - rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); - if( rc!=SQLITE_OK ) return rc; + if( p->bStat1 ){ + /* Check if there is a conflicting row. For sqlite_stat1, this needs + ** to be done using a SELECT, as there is no PRIMARY KEY in the + ** database schema to throw an exception if a duplicate is inserted. */ + rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect); + if( rc==SQLITE_ROW ){ + rc = SQLITE_CONSTRAINT; + sqlite3_reset(p->pSelect); + } + } + + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pInsert); + rc = sqlite3_reset(p->pInsert); + } - sqlite3_step(p->pInsert); - rc = sqlite3_reset(p->pInsert); if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace @@ -180630,42 +186479,42 @@ static int sessionApplyOneWithRetry( int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); - assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); - - /* If the bRetry flag is set, the change has not been applied due to an - ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and - ** a row with the correct PK is present in the db, but one or more other - ** fields do not contain the expected values) and the conflict handler - ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, - ** but pass NULL as the final argument so that sessionApplyOneOp() ignores - ** the SQLITE_CHANGESET_DATA problem. */ - if( bRetry ){ - assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); - } - - /* If the bReplace flag is set, the change is an INSERT that has not - ** been performed because the database already contains a row with the - ** specified primary key and the conflict handler returned - ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row - ** before reattempting the INSERT. */ - else if( bReplace ){ - assert( pIter->op==SQLITE_INSERT ); - rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sessionBindRow(pIter, - sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); - sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); - } - if( rc==SQLITE_OK ){ - sqlite3_step(pApply->pDelete); - rc = sqlite3_reset(pApply->pDelete); - } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ + /* If the bRetry flag is set, the change has not been applied due to an + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and + ** a row with the correct PK is present in the db, but one or more other + ** fields do not contain the expected values) and the conflict handler + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores + ** the SQLITE_CHANGESET_DATA problem. */ + if( bRetry ){ + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + + /* If the bReplace flag is set, the change is an INSERT that has not + ** been performed because the database already contains a row with the + ** specified primary key and the conflict handler returned + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row + ** before reattempting the INSERT. */ + else if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pApply->pDelete); + rc = sqlite3_reset(pApply->pDelete); + } + if( rc==SQLITE_OK ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + } } } @@ -180741,10 +186590,12 @@ static int sessionChangesetApply( int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), - void *pCtx /* First argument passed to xConflict */ + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase information */ + int flags /* SESSION_APPLY_XXX flags */ ){ int schemaMismatch = 0; - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ @@ -180755,7 +186606,9 @@ static int sessionChangesetApply( pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sqlite3_mutex_enter(sqlite3_db_mutex(db)); - rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + } if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); } @@ -180779,9 +186632,18 @@ static int sessionChangesetApply( sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pSelect); - memset(&sApply, 0, sizeof(sApply)); sApply.db = db; + sApply.pDelete = 0; + sApply.pUpdate = 0; + sApply.pInsert = 0; + sApply.pSelect = 0; + sApply.nCol = 0; + sApply.azCol = 0; + sApply.abPK = 0; + sApply.bStat1 = 0; sApply.bDeferConstraints = 1; + sApply.bRebaseStarted = 0; + memset(&sApply.constraints, 0, sizeof(SessionBuffer)); /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns @@ -180830,12 +186692,20 @@ static int sessionChangesetApply( } else{ sApply.nCol = nCol; - if((rc = sessionSelectRow(db, zTab, &sApply)) - || (rc = sessionUpdateRow(db, zTab, &sApply)) - || (rc = sessionDeleteRow(db, zTab, &sApply)) - || (rc = sessionInsertRow(db, zTab, &sApply)) - ){ - break; + if( 0==sqlite3_stricmp(zTab, "sqlite_stat1") ){ + if( (rc = sessionStat1Sql(db, &sApply) ) ){ + break; + } + sApply.bStat1 = 1; + }else{ + if((rc = sessionSelectRow(db, zTab, &sApply)) + || (rc = sessionUpdateRow(db, zTab, &sApply)) + || (rc = sessionDeleteRow(db, zTab, &sApply)) + || (rc = sessionInsertRow(db, zTab, &sApply)) + ){ + break; + } + sApply.bStat1 = 0; } } nTab = sqlite3Strlen30(zTab); @@ -180876,23 +186746,62 @@ static int sessionChangesetApply( } sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); - }else{ - sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); - sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + }else{ + sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); + sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + } } + if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ + *ppRebase = (void*)sApply.rebase.aBuf; + *pnRebase = sApply.rebase.nBuf; + sApply.rebase.aBuf = 0; + } sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pSelect); sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_free((char*)sApply.constraints.aBuf); + sqlite3_free((char*)sApply.rebase.aBuf); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } +/* +** Apply the changeset passed via pChangeset/nChangeset to the main +** database attached to handle "db". +*/ +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags + ); + } + return rc; +} + /* ** Apply the changeset passed via pChangeset/nChangeset to the main database ** attached to handle "db". Invoke the supplied conflict handler callback @@ -180913,12 +186822,9 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); - } - return rc; + return sqlite3changeset_apply_v2( + db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 + ); } /* @@ -180926,6 +186832,32 @@ SQLITE_API int sqlite3changeset_apply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags + ); + } + return rc; +} SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ @@ -180941,12 +186873,9 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); - } - return rc; + return sqlite3changeset_apply_v2_strm( + db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0 + ); } /* @@ -180965,6 +186894,7 @@ struct sqlite3_changegroup { */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ + int bRebase, /* True for a rebase hash-table */ int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ @@ -180974,6 +186904,7 @@ static int sessionChangeMerge( SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; + int rc = SQLITE_OK; if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); @@ -180983,9 +186914,66 @@ static int sessionChangeMerge( memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; - pNew->nRecord = nRec; pNew->aRecord = (u8*)&pNew[1]; - memcpy(pNew->aRecord, aRec, nRec); + if( bIndirect==0 || bRebase==0 ){ + pNew->nRecord = nRec; + memcpy(pNew->aRecord, aRec, nRec); + }else{ + int i; + u8 *pIn = aRec; + u8 *pOut = pNew->aRecord; + for(i=0; inCol; i++){ + int nIn = sessionSerialLen(pIn); + if( *pIn==0 ){ + *pOut++ = 0; + }else if( pTab->abPK[i]==0 ){ + *pOut++ = 0xFF; + }else{ + memcpy(pOut, pIn, nIn); + pOut += nIn; + } + pIn += nIn; + } + pNew->nRecord = pOut - pNew->aRecord; + } + }else if( bRebase ){ + if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){ + *ppNew = pExist; + }else{ + int nByte = nRec + pExist->nRecord + sizeof(SessionChange); + pNew = (SessionChange*)sqlite3_malloc(nByte); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + int i; + u8 *a1 = pExist->aRecord; + u8 *a2 = aRec; + u8 *pOut; + + memset(pNew, 0, nByte); + pNew->bIndirect = bIndirect || pExist->bIndirect; + pNew->op = op2; + pOut = pNew->aRecord = (u8*)&pNew[1]; + + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){ + *pOut++ = 0xFF; + }else if( *a2==0 ){ + memcpy(pOut, a1, n1); + pOut += n1; + }else{ + memcpy(pOut, a2, n2); + pOut += n2; + } + a1 += n1; + a2 += n2; + } + pNew->nRecord = pOut - pNew->aRecord; + } + sqlite3_free(pExist); + } }else{ int op1 = pExist->op; @@ -181079,7 +187067,7 @@ static int sessionChangeMerge( } *ppNew = pNew; - return SQLITE_OK; + return rc; } /* @@ -181088,15 +187076,15 @@ static int sessionChangeMerge( */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ - sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ + sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ + int bRebase /* True if hash table is for rebasing */ ){ u8 *aRec; int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; - - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ const char *zNew; int nCol; int op; @@ -181176,7 +187164,7 @@ static int sessionChangesetToHash( } } - rc = sessionChangeMerge(pTab, + rc = sessionChangeMerge(pTab, bRebase, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); if( rc ) break; @@ -181284,7 +187272,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp); + rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; @@ -181315,7 +187303,7 @@ SQLITE_API int sqlite3changegroup_add_strm( rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp); + rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; @@ -181400,6 +187388,349 @@ SQLITE_API int sqlite3changeset_concat_strm( return rc; } +/* +** Changeset rebaser handle. +*/ +struct sqlite3_rebaser { + sqlite3_changegroup grp; /* Hash table */ +}; + +/* +** Buffers a1 and a2 must both contain a sessions module record nCol +** fields in size. This function appends an nCol sessions module +** record to buffer pBuf that is a copy of a1, except that for +** each field that is undefined in a1[], swap in the field from a2[]. +*/ +static void sessionAppendRecordMerge( + SessionBuffer *pBuf, /* Buffer to append to */ + int nCol, /* Number of columns in each record */ + u8 *a1, int n1, /* Record 1 */ + u8 *a2, int n2, /* Record 2 */ + int *pRc /* IN/OUT: error code */ +){ + sessionBufferGrow(pBuf, n1+n2, pRc); + if( *pRc==SQLITE_OK ){ + int i; + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; + for(i=0; inBuf = pOut-pBuf->aBuf; + assert( pBuf->nBuf<=pBuf->nAlloc ); + } +} + +/* +** This function is called when rebasing a local UPDATE change against one +** or more remote UPDATE changes. The aRec/nRec buffer contains the current +** old.* and new.* records for the change. The rebase buffer (a single +** record) is in aChange/nChange. The rebased change is appended to buffer +** pBuf. +** +** Rebasing the UPDATE involves: +** +** * Removing any changes to fields for which the corresponding field +** in the rebase buffer is set to "replaced" (type 0xFF). If this +** means the UPDATE change updates no fields, nothing is appended +** to the output buffer. +** +** * For each field modified by the local change for which the +** corresponding field in the rebase buffer is not "undefined" (0x00) +** or "replaced" (0xFF), the old.* value is replaced by the value +** in the rebase buffer. +*/ +static void sessionAppendPartialUpdate( + SessionBuffer *pBuf, /* Append record here */ + sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */ + u8 *aRec, int nRec, /* Local change */ + u8 *aChange, int nChange, /* Record to rebase against */ + int *pRc /* IN/OUT: Return Code */ +){ + sessionBufferGrow(pBuf, 2+nRec+nChange, pRc); + if( *pRc==SQLITE_OK ){ + int bData = 0; + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; + int i; + u8 *a1 = aRec; + u8 *a2 = aChange; + + *pOut++ = SQLITE_UPDATE; + *pOut++ = pIter->bIndirect; + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( pIter->abPK[i] || a2[0]==0 ){ + if( !pIter->abPK[i] ) bData = 1; + memcpy(pOut, a1, n1); + pOut += n1; + }else if( a2[0]!=0xFF ){ + bData = 1; + memcpy(pOut, a2, n2); + pOut += n2; + }else{ + *pOut++ = '\0'; + } + a1 += n1; + a2 += n2; + } + if( bData ){ + a2 = aChange; + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( pIter->abPK[i] || a2[0]!=0xFF ){ + memcpy(pOut, a1, n1); + pOut += n1; + }else{ + *pOut++ = '\0'; + } + a1 += n1; + a2 += n2; + } + pBuf->nBuf = (pOut - pBuf->aBuf); + } + } +} + +/* +** pIter is configured to iterate through a changeset. This function rebases +** that changeset according to the current configuration of the rebaser +** object passed as the first argument. If no error occurs and argument xOutput +** is not NULL, then the changeset is returned to the caller by invoking +** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL, +** then (*ppOut) is set to point to a buffer containing the rebased changeset +** before this function returns. In this case (*pnOut) is set to the size of +** the buffer in bytes. It is the responsibility of the caller to eventually +** free the (*ppOut) buffer using sqlite3_free(). +** +** If an error occurs, an SQLite error code is returned. If ppOut and +** pnOut are not NULL, then the two output parameters are set to 0 before +** returning. +*/ +static int sessionRebase( + sqlite3_rebaser *p, /* Rebaser hash table */ + sqlite3_changeset_iter *pIter, /* Input data */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, /* Context for xOutput callback */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Inverse of pChangeset */ +){ + int rc = SQLITE_OK; + u8 *aRec = 0; + int nRec = 0; + int bNew = 0; + SessionTable *pTab = 0; + SessionBuffer sOut = {0,0,0}; + + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ + SessionChange *pChange = 0; + int bDone = 0; + + if( bNew ){ + const char *zTab = pIter->zTab; + for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; + } + bNew = 0; + + /* A patchset may not be rebased */ + if( pIter->bPatchset ){ + rc = SQLITE_ERROR; + } + + /* Append a table header to the output for this new table */ + sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); + sessionAppendVarint(&sOut, pIter->nCol, &rc); + sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); + sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc); + } + + if( pTab && rc==SQLITE_OK ){ + int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); + + for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ + if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ + break; + } + } + } + + if( pChange ){ + assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); + switch( pIter->op ){ + case SQLITE_INSERT: + if( pChange->op==SQLITE_INSERT ){ + bDone = 1; + if( pChange->bIndirect==0 ){ + sessionAppendByte(&sOut, SQLITE_UPDATE, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc); + sessionAppendBlob(&sOut, aRec, nRec, &rc); + } + } + break; + + case SQLITE_UPDATE: + bDone = 1; + if( pChange->op==SQLITE_DELETE ){ + if( pChange->bIndirect==0 ){ + u8 *pCsr = aRec; + sessionSkipRecord(&pCsr, pIter->nCol); + sessionAppendByte(&sOut, SQLITE_INSERT, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendRecordMerge(&sOut, pIter->nCol, + pCsr, nRec-(pCsr-aRec), + pChange->aRecord, pChange->nRecord, &rc + ); + } + }else{ + sessionAppendPartialUpdate(&sOut, pIter, + aRec, nRec, pChange->aRecord, pChange->nRecord, &rc + ); + } + break; + + default: + assert( pIter->op==SQLITE_DELETE ); + bDone = 1; + if( pChange->op==SQLITE_INSERT ){ + sessionAppendByte(&sOut, SQLITE_DELETE, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendRecordMerge(&sOut, pIter->nCol, + pChange->aRecord, pChange->nRecord, aRec, nRec, &rc + ); + } + break; + } + } + + if( bDone==0 ){ + sessionAppendByte(&sOut, pIter->op, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendBlob(&sOut, aRec, nRec, &rc); + } + if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + } + if( rc ) break; + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(sOut.aBuf); + memset(&sOut, 0, sizeof(sOut)); + } + + if( rc==SQLITE_OK ){ + if( xOutput ){ + if( sOut.nBuf>0 ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + } + }else{ + *ppOut = (void*)sOut.aBuf; + *pnOut = sOut.nBuf; + sOut.aBuf = 0; + } + } + sqlite3_free(sOut.aBuf); + return rc; +} + +/* +** Create a new rebaser object. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ + int rc = SQLITE_OK; + sqlite3_rebaser *pNew; + + pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pNew, 0, sizeof(sqlite3_rebaser)); + } + *ppNew = pNew; + return rc; +} + +/* +** Call this one or more times to configure a rebaser. +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser *p, + int nRebase, const void *pRebase +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, &p->grp, 1); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Rebase a changeset according to current rebaser configuration +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser *p, + int nIn, const void *pIn, + int *pnOut, void **ppOut +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ + int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); + + if( rc==SQLITE_OK ){ + rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); + sqlite3changeset_finalize(pIter); + } + + return rc; +} + +/* +** Rebase a changeset according to current rebaser configuration +*/ +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *p, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + + if( rc==SQLITE_OK ){ + rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); + sqlite3changeset_finalize(pIter); + } + + return rc; +} + +/* +** Destroy a rebaser object +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ + if( p ){ + sessionDeleteTable(p->grp.pList); + sqlite3_free(p); + } +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ /************** End of sqlite3session.c **************************************/ @@ -183524,7 +189855,7 @@ static int jsonEachColumn( } if( p->eType==JSON_ARRAY ){ jsonPrintf(30, &x, "[%d]", p->iRowid); - }else{ + }else if( p->eType==JSON_OBJECT ){ jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); } } @@ -185149,6 +191480,8 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm( int bPrefix ); +static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*); + static Fts5ExprNearset *sqlite3Fts5ParseNearset( Fts5Parse*, Fts5ExprNearset*, @@ -185229,9 +191562,10 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); #define FTS5_STRING 9 #define FTS5_LP 10 #define FTS5_RP 11 -#define FTS5_COMMA 12 -#define FTS5_PLUS 13 -#define FTS5_STAR 14 +#define FTS5_CARET 12 +#define FTS5_COMMA 13 +#define FTS5_PLUS 14 +#define FTS5_STAR 15 /* ** 2000-05-29 @@ -185326,27 +191660,30 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); ** zero the stack is dynamically sized using realloc() ** sqlite3Fts5ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3Fts5ParserARG_PDECL A parameter declaration for the %extra_argument +** sqlite3Fts5ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser +** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context ** fts5YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** fts5YYNSTATE the combined number of states. ** fts5YYNRULE the number of rules in the grammar +** fts5YYNFTS5TOKEN Number of terminal symbols ** fts5YY_MAX_SHIFT Maximum value for shift actions ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** fts5YY_MIN_REDUCE Minimum value for reduce actions -** fts5YY_MAX_REDUCE Maximum value for reduce actions ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op +** fts5YY_MIN_REDUCE Minimum value for reduce actions +** fts5YY_MAX_REDUCE Maximum value for reduce actions */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define fts5YYCODETYPE unsigned char -#define fts5YYNOCODE 28 +#define fts5YYNOCODE 27 #define fts5YYACTIONTYPE unsigned char #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token typedef union { @@ -185363,18 +191700,25 @@ typedef union { #endif #define sqlite3Fts5ParserARG_SDECL Fts5Parse *pParse; #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse -#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse -#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse -#define fts5YYNSTATE 33 -#define fts5YYNRULE 27 -#define fts5YY_MAX_SHIFT 32 -#define fts5YY_MIN_SHIFTREDUCE 50 -#define fts5YY_MAX_SHIFTREDUCE 76 -#define fts5YY_MIN_REDUCE 77 -#define fts5YY_MAX_REDUCE 103 -#define fts5YY_ERROR_ACTION 104 -#define fts5YY_ACCEPT_ACTION 105 -#define fts5YY_NO_ACTION 106 +#define sqlite3Fts5ParserARG_PARAM ,pParse +#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; +#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; +#define sqlite3Fts5ParserCTX_SDECL +#define sqlite3Fts5ParserCTX_PDECL +#define sqlite3Fts5ParserCTX_PARAM +#define sqlite3Fts5ParserCTX_FETCH +#define sqlite3Fts5ParserCTX_STORE +#define fts5YYNSTATE 35 +#define fts5YYNRULE 28 +#define fts5YYNFTS5TOKEN 16 +#define fts5YY_MAX_SHIFT 34 +#define fts5YY_MIN_SHIFTREDUCE 52 +#define fts5YY_MAX_SHIFTREDUCE 79 +#define fts5YY_ERROR_ACTION 80 +#define fts5YY_ACCEPT_ACTION 81 +#define fts5YY_NO_ACTION 82 +#define fts5YY_MIN_REDUCE 83 +#define fts5YY_MAX_REDUCE 110 /************* End control #defines *******************************************/ /* Define the fts5yytestcase() macro to be a no-op if is not already defined @@ -185404,9 +191748,6 @@ typedef union { ** N between fts5YY_MIN_SHIFTREDUCE Shift to an arbitrary state then ** and fts5YY_MAX_SHIFTREDUCE reduce by rule N-fts5YY_MIN_SHIFTREDUCE. ** -** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE -** and fts5YY_MAX_REDUCE -** ** N == fts5YY_ERROR_ACTION A syntax error has occurred. ** ** N == fts5YY_ACCEPT_ACTION The parser accepts its input. @@ -185414,25 +191755,22 @@ typedef union { ** N == fts5YY_NO_ACTION No such action. Denotes unused ** slots in the fts5yy_action[] table. ** +** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE +** and fts5YY_MAX_REDUCE +** ** The action table is constructed as a single large table named fts5yy_action[]. ** Given state S and lookahead X, the action is computed as either: ** ** (A) N = fts5yy_action[ fts5yy_shift_ofst[S] + X ] ** (B) N = fts5yy_default[S] ** -** The (A) formula is preferred. The B formula is used instead if: -** (1) The fts5yy_shift_ofst[S]+X value is out of range, or -** (2) fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X, or -** (3) fts5yy_shift_ofst[S] equal fts5YY_SHIFT_USE_DFLT. -** (Implementation note: fts5YY_SHIFT_USE_DFLT is chosen so that -** fts5YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. -** Hence only tests (1) and (2) need to be evaluated.) +** The (A) formula is preferred. The B formula is used instead if +** fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X. ** ** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the fts5yy_reduce_ofst[] array is used in place of -** the fts5yy_shift_ofst[] array and fts5YY_REDUCE_USE_DFLT is used in place of -** fts5YY_SHIFT_USE_DFLT. +** the fts5yy_shift_ofst[] array. ** ** The following are the tables generated in this section: ** @@ -185446,54 +191784,56 @@ typedef union { ** fts5yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define fts5YY_ACTTAB_COUNT (98) +#define fts5YY_ACTTAB_COUNT (105) static const fts5YYACTIONTYPE fts5yy_action[] = { - /* 0 */ 105, 19, 90, 6, 26, 93, 92, 24, 24, 17, - /* 10 */ 90, 6, 26, 16, 92, 54, 24, 18, 90, 6, - /* 20 */ 26, 10, 92, 12, 24, 75, 86, 90, 6, 26, - /* 30 */ 13, 92, 75, 24, 20, 90, 6, 26, 101, 92, - /* 40 */ 56, 24, 27, 90, 6, 26, 100, 92, 21, 24, - /* 50 */ 23, 15, 30, 11, 1, 91, 22, 25, 9, 92, - /* 60 */ 7, 24, 3, 4, 5, 3, 4, 5, 3, 77, - /* 70 */ 4, 5, 3, 61, 23, 15, 60, 11, 80, 12, - /* 80 */ 2, 13, 68, 10, 29, 52, 55, 75, 31, 32, - /* 90 */ 8, 28, 5, 3, 51, 55, 72, 14, + /* 0 */ 81, 20, 96, 6, 28, 99, 98, 26, 26, 18, + /* 10 */ 96, 6, 28, 17, 98, 56, 26, 19, 96, 6, + /* 20 */ 28, 14, 98, 14, 26, 31, 92, 96, 6, 28, + /* 30 */ 108, 98, 25, 26, 21, 96, 6, 28, 78, 98, + /* 40 */ 58, 26, 29, 96, 6, 28, 107, 98, 22, 26, + /* 50 */ 24, 16, 12, 11, 1, 13, 13, 24, 16, 23, + /* 60 */ 11, 33, 34, 13, 97, 8, 27, 32, 98, 7, + /* 70 */ 26, 3, 4, 5, 3, 4, 5, 3, 83, 4, + /* 80 */ 5, 3, 63, 5, 3, 62, 12, 2, 86, 13, + /* 90 */ 9, 30, 10, 10, 54, 57, 75, 78, 78, 53, + /* 100 */ 57, 15, 82, 82, 71, }; static const fts5YYCODETYPE fts5yy_lookahead[] = { /* 0 */ 16, 17, 18, 19, 20, 22, 22, 24, 24, 17, /* 10 */ 18, 19, 20, 7, 22, 9, 24, 17, 18, 19, - /* 20 */ 20, 10, 22, 9, 24, 14, 17, 18, 19, 20, - /* 30 */ 9, 22, 14, 24, 17, 18, 19, 20, 26, 22, + /* 20 */ 20, 9, 22, 9, 24, 13, 17, 18, 19, 20, + /* 30 */ 26, 22, 24, 24, 17, 18, 19, 20, 15, 22, /* 40 */ 9, 24, 17, 18, 19, 20, 26, 22, 21, 24, - /* 50 */ 6, 7, 13, 9, 10, 18, 21, 20, 5, 22, - /* 60 */ 5, 24, 3, 1, 2, 3, 1, 2, 3, 0, - /* 70 */ 1, 2, 3, 11, 6, 7, 11, 9, 5, 9, - /* 80 */ 10, 9, 11, 10, 12, 8, 9, 14, 24, 25, - /* 90 */ 23, 24, 2, 3, 8, 9, 9, 9, + /* 50 */ 6, 7, 9, 9, 10, 12, 12, 6, 7, 21, + /* 60 */ 9, 24, 25, 12, 18, 5, 20, 14, 22, 5, + /* 70 */ 24, 3, 1, 2, 3, 1, 2, 3, 0, 1, + /* 80 */ 2, 3, 11, 2, 3, 11, 9, 10, 5, 12, + /* 90 */ 23, 24, 10, 10, 8, 9, 9, 15, 15, 8, + /* 100 */ 9, 9, 27, 27, 11, 27, 27, 27, 27, 27, + /* 110 */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + /* 120 */ 27, }; -#define fts5YY_SHIFT_USE_DFLT (98) -#define fts5YY_SHIFT_COUNT (32) +#define fts5YY_SHIFT_COUNT (34) #define fts5YY_SHIFT_MIN (0) -#define fts5YY_SHIFT_MAX (90) +#define fts5YY_SHIFT_MAX (93) static const unsigned char fts5yy_shift_ofst[] = { - /* 0 */ 44, 44, 44, 44, 44, 44, 68, 70, 72, 14, - /* 10 */ 21, 73, 11, 18, 18, 31, 31, 62, 65, 69, - /* 20 */ 90, 77, 86, 6, 39, 53, 55, 59, 39, 87, - /* 30 */ 88, 39, 71, + /* 0 */ 44, 44, 44, 44, 44, 44, 51, 77, 43, 12, + /* 10 */ 14, 83, 82, 14, 23, 23, 31, 31, 71, 74, + /* 20 */ 78, 81, 86, 91, 6, 53, 53, 60, 64, 68, + /* 30 */ 53, 87, 92, 53, 93, }; -#define fts5YY_REDUCE_USE_DFLT (-18) -#define fts5YY_REDUCE_COUNT (16) +#define fts5YY_REDUCE_COUNT (17) #define fts5YY_REDUCE_MIN (-17) #define fts5YY_REDUCE_MAX (67) static const signed char fts5yy_reduce_ofst[] = { - /* 0 */ -16, -8, 0, 9, 17, 25, 37, -17, 64, -17, - /* 10 */ 67, 12, 12, 12, 20, 27, 35, + /* 0 */ -16, -8, 0, 9, 17, 25, 46, -17, -17, 37, + /* 10 */ 67, 4, 4, 8, 4, 20, 27, 38, }; static const fts5YYACTIONTYPE fts5yy_default[] = { - /* 0 */ 104, 104, 104, 104, 104, 104, 89, 104, 98, 104, - /* 10 */ 104, 103, 103, 103, 103, 104, 104, 104, 104, 104, - /* 20 */ 85, 104, 104, 104, 94, 104, 104, 84, 96, 104, - /* 30 */ 104, 97, 104, + /* 0 */ 80, 80, 80, 80, 80, 80, 95, 80, 80, 105, + /* 10 */ 80, 110, 110, 80, 110, 110, 80, 80, 80, 80, + /* 20 */ 80, 91, 80, 80, 80, 101, 100, 80, 80, 90, + /* 30 */ 103, 80, 80, 104, 80, }; /********** End of lemon-generated parsing tables *****************************/ @@ -185552,6 +191892,7 @@ struct fts5yyParser { int fts5yyerrcnt; /* Shifts left before out of the error */ #endif sqlite3Fts5ParserARG_SDECL /* A place to hold %extra_argument */ + sqlite3Fts5ParserCTX_SDECL /* A place to hold %extra_context */ #if fts5YYSTACKDEPTH<=0 int fts5yystksz; /* Current side of the stack */ fts5yyStackEntry *fts5yystack; /* The parser's stack */ @@ -185595,19 +191936,39 @@ static void sqlite3Fts5ParserTrace(FILE *TraceFILE, char *zTracePrompt){ } #endif /* NDEBUG */ -#ifndef NDEBUG +#if defined(fts5YYCOVERAGE) || !defined(NDEBUG) /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const fts5yyTokenName[] = { - "$", "OR", "AND", "NOT", - "TERM", "COLON", "MINUS", "LCP", - "RCP", "STRING", "LP", "RP", - "COMMA", "PLUS", "STAR", "error", - "input", "expr", "cnearset", "exprlist", - "colset", "colsetlist", "nearset", "nearphrases", - "phrase", "neardist_opt", "star_opt", + /* 0 */ "$", + /* 1 */ "OR", + /* 2 */ "AND", + /* 3 */ "NOT", + /* 4 */ "TERM", + /* 5 */ "COLON", + /* 6 */ "MINUS", + /* 7 */ "LCP", + /* 8 */ "RCP", + /* 9 */ "STRING", + /* 10 */ "LP", + /* 11 */ "RP", + /* 12 */ "CARET", + /* 13 */ "COMMA", + /* 14 */ "PLUS", + /* 15 */ "STAR", + /* 16 */ "input", + /* 17 */ "expr", + /* 18 */ "cnearset", + /* 19 */ "exprlist", + /* 20 */ "colset", + /* 21 */ "colsetlist", + /* 22 */ "nearset", + /* 23 */ "nearphrases", + /* 24 */ "phrase", + /* 25 */ "neardist_opt", + /* 26 */ "star_opt", }; -#endif /* NDEBUG */ +#endif /* defined(fts5YYCOVERAGE) || !defined(NDEBUG) */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. @@ -185631,15 +191992,16 @@ static const char *const fts5yyRuleName[] = { /* 15 */ "cnearset ::= nearset", /* 16 */ "cnearset ::= colset COLON nearset", /* 17 */ "nearset ::= phrase", - /* 18 */ "nearset ::= STRING LP nearphrases neardist_opt RP", - /* 19 */ "nearphrases ::= phrase", - /* 20 */ "nearphrases ::= nearphrases phrase", - /* 21 */ "neardist_opt ::=", - /* 22 */ "neardist_opt ::= COMMA STRING", - /* 23 */ "phrase ::= phrase PLUS STRING star_opt", - /* 24 */ "phrase ::= STRING star_opt", - /* 25 */ "star_opt ::= STAR", - /* 26 */ "star_opt ::=", + /* 18 */ "nearset ::= CARET phrase", + /* 19 */ "nearset ::= STRING LP nearphrases neardist_opt RP", + /* 20 */ "nearphrases ::= phrase", + /* 21 */ "nearphrases ::= nearphrases phrase", + /* 22 */ "neardist_opt ::=", + /* 23 */ "neardist_opt ::= COMMA STRING", + /* 24 */ "phrase ::= phrase PLUS STRING star_opt", + /* 25 */ "phrase ::= STRING star_opt", + /* 26 */ "star_opt ::= STAR", + /* 27 */ "star_opt ::=", }; #endif /* NDEBUG */ @@ -185688,28 +192050,29 @@ static int fts5yyGrowStack(fts5yyParser *p){ /* Initialize a new parser that has already been allocated. */ -static void sqlite3Fts5ParserInit(void *fts5yypParser){ - fts5yyParser *pParser = (fts5yyParser*)fts5yypParser; +static void sqlite3Fts5ParserInit(void *fts5yypRawParser sqlite3Fts5ParserCTX_PDECL){ + fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yypRawParser; + sqlite3Fts5ParserCTX_STORE #ifdef fts5YYTRACKMAXSTACKDEPTH - pParser->fts5yyhwm = 0; + fts5yypParser->fts5yyhwm = 0; #endif #if fts5YYSTACKDEPTH<=0 - pParser->fts5yytos = NULL; - pParser->fts5yystack = NULL; - pParser->fts5yystksz = 0; - if( fts5yyGrowStack(pParser) ){ - pParser->fts5yystack = &pParser->fts5yystk0; - pParser->fts5yystksz = 1; + fts5yypParser->fts5yytos = NULL; + fts5yypParser->fts5yystack = NULL; + fts5yypParser->fts5yystksz = 0; + if( fts5yyGrowStack(fts5yypParser) ){ + fts5yypParser->fts5yystack = &fts5yypParser->fts5yystk0; + fts5yypParser->fts5yystksz = 1; } #endif #ifndef fts5YYNOERRORRECOVERY - pParser->fts5yyerrcnt = -1; + fts5yypParser->fts5yyerrcnt = -1; #endif - pParser->fts5yytos = pParser->fts5yystack; - pParser->fts5yystack[0].stateno = 0; - pParser->fts5yystack[0].major = 0; + fts5yypParser->fts5yytos = fts5yypParser->fts5yystack; + fts5yypParser->fts5yystack[0].stateno = 0; + fts5yypParser->fts5yystack[0].major = 0; #if fts5YYSTACKDEPTH>0 - pParser->fts5yystackEnd = &pParser->fts5yystack[fts5YYSTACKDEPTH-1]; + fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; #endif } @@ -185726,11 +192089,14 @@ static void sqlite3Fts5ParserInit(void *fts5yypParser){ ** A pointer to a parser. This pointer is used in subsequent calls ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree. */ -static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ - fts5yyParser *pParser; - pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); - if( pParser ) sqlite3Fts5ParserInit(pParser); - return pParser; +static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE) sqlite3Fts5ParserCTX_PDECL){ + fts5yyParser *fts5yypParser; + fts5yypParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); + if( fts5yypParser ){ + sqlite3Fts5ParserCTX_STORE + sqlite3Fts5ParserInit(fts5yypParser sqlite3Fts5ParserCTX_PARAM); + } + return (void*)fts5yypParser; } #endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ @@ -185747,7 +192113,8 @@ static void fts5yy_destructor( fts5YYCODETYPE fts5yymajor, /* Type code for object to destroy */ fts5YYMINORTYPE *fts5yypminor /* The object to be destroyed */ ){ - sqlite3Fts5ParserARG_FETCH; + sqlite3Fts5ParserARG_FETCH + sqlite3Fts5ParserCTX_FETCH switch( fts5yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -185857,24 +192224,66 @@ static int sqlite3Fts5ParserStackPeak(void *p){ } #endif +/* This array of booleans keeps track of the parser statement +** coverage. The element fts5yycoverage[X][Y] is set when the parser +** is in state X and has a lookahead token Y. In a well-tested +** systems, every element of this matrix should end up being set. +*/ +#if defined(fts5YYCOVERAGE) +static unsigned char fts5yycoverage[fts5YYNSTATE][fts5YYNFTS5TOKEN]; +#endif + +/* +** Write into out a description of every state/lookahead combination that +** +** (1) has not been used by the parser, and +** (2) is not a syntax error. +** +** Return the number of missed state/lookahead combinations. +*/ +#if defined(fts5YYCOVERAGE) +static int sqlite3Fts5ParserCoverage(FILE *out){ + int stateno, iLookAhead, i; + int nMissed = 0; + for(stateno=0; statenofts5yytos->stateno; - - if( stateno>=fts5YY_MIN_REDUCE ) return stateno; + + if( stateno>fts5YY_MAX_SHIFT ) return stateno; assert( stateno <= fts5YY_SHIFT_COUNT ); +#if defined(fts5YYCOVERAGE) + fts5yycoverage[stateno][iLookAhead] = 1; +#endif do{ i = fts5yy_shift_ofst[stateno]; + assert( i>=0 ); + assert( i+fts5YYNFTS5TOKEN<=(int)sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) ); assert( iLookAhead!=fts5YYNOCODE ); + assert( iLookAhead < fts5YYNFTS5TOKEN ); i += iLookAhead; - if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ + if( fts5yy_lookahead[i]!=iLookAhead ){ #ifdef fts5YYFALLBACK fts5YYCODETYPE iFallback; /* Fallback token */ if( iLookAheadfts5yytos->major], + fprintf(fts5yyTraceFILE,"%s%s '%s', go to state %d\n", + fts5yyTracePrompt, zTag, fts5yyTokenName[fts5yypParser->fts5yytos->major], fts5yyNewState); }else{ - fprintf(fts5yyTraceFILE,"%sShift '%s'\n", - fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major]); + fprintf(fts5yyTraceFILE,"%s%s '%s', pending reduce %d\n", + fts5yyTracePrompt, zTag, fts5yyTokenName[fts5yypParser->fts5yytos->major], + fts5yyNewState - fts5YY_MIN_REDUCE); } } } #else -# define fts5yyTraceShift(X,Y) +# define fts5yyTraceShift(X,Y,Z) #endif /* @@ -185996,8 +192407,8 @@ static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState){ */ static void fts5yy_shift( fts5yyParser *fts5yypParser, /* The parser to be shifted */ - int fts5yyNewState, /* The new state to shift in */ - int fts5yyMajor, /* The major token to shift in */ + fts5YYACTIONTYPE fts5yyNewState, /* The new state to shift in */ + fts5YYCODETYPE fts5yyMajor, /* The major token to shift in */ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyMinor /* The minor token to shift in */ ){ fts5yyStackEntry *fts5yytos; @@ -186027,10 +192438,10 @@ static void fts5yy_shift( fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; } fts5yytos = fts5yypParser->fts5yytos; - fts5yytos->stateno = (fts5YYACTIONTYPE)fts5yyNewState; - fts5yytos->major = (fts5YYCODETYPE)fts5yyMajor; + fts5yytos->stateno = fts5yyNewState; + fts5yytos->major = fts5yyMajor; fts5yytos->minor.fts5yy0 = fts5yyMinor; - fts5yyTraceShift(fts5yypParser, fts5yyNewState); + fts5yyTraceShift(fts5yypParser, fts5yyNewState, "Shift"); } /* The following table contains information about every rule that @@ -186040,33 +192451,34 @@ static const struct { fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ signed char nrhs; /* Negative of the number of RHS symbols in the rule */ } fts5yyRuleInfo[] = { - { 16, -1 }, - { 20, -4 }, - { 20, -3 }, - { 20, -1 }, - { 20, -2 }, - { 21, -2 }, - { 21, -1 }, - { 17, -3 }, - { 17, -3 }, - { 17, -3 }, - { 17, -5 }, - { 17, -3 }, - { 17, -1 }, - { 19, -1 }, - { 19, -2 }, - { 18, -1 }, - { 18, -3 }, - { 22, -1 }, - { 22, -5 }, - { 23, -1 }, - { 23, -2 }, - { 25, 0 }, - { 25, -2 }, - { 24, -4 }, - { 24, -2 }, - { 26, -1 }, - { 26, 0 }, + { 16, -1 }, /* (0) input ::= expr */ + { 20, -4 }, /* (1) colset ::= MINUS LCP colsetlist RCP */ + { 20, -3 }, /* (2) colset ::= LCP colsetlist RCP */ + { 20, -1 }, /* (3) colset ::= STRING */ + { 20, -2 }, /* (4) colset ::= MINUS STRING */ + { 21, -2 }, /* (5) colsetlist ::= colsetlist STRING */ + { 21, -1 }, /* (6) colsetlist ::= STRING */ + { 17, -3 }, /* (7) expr ::= expr AND expr */ + { 17, -3 }, /* (8) expr ::= expr OR expr */ + { 17, -3 }, /* (9) expr ::= expr NOT expr */ + { 17, -5 }, /* (10) expr ::= colset COLON LP expr RP */ + { 17, -3 }, /* (11) expr ::= LP expr RP */ + { 17, -1 }, /* (12) expr ::= exprlist */ + { 19, -1 }, /* (13) exprlist ::= cnearset */ + { 19, -2 }, /* (14) exprlist ::= exprlist cnearset */ + { 18, -1 }, /* (15) cnearset ::= nearset */ + { 18, -3 }, /* (16) cnearset ::= colset COLON nearset */ + { 22, -1 }, /* (17) nearset ::= phrase */ + { 22, -2 }, /* (18) nearset ::= CARET phrase */ + { 22, -5 }, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ + { 23, -1 }, /* (20) nearphrases ::= phrase */ + { 23, -2 }, /* (21) nearphrases ::= nearphrases phrase */ + { 25, 0 }, /* (22) neardist_opt ::= */ + { 25, -2 }, /* (23) neardist_opt ::= COMMA STRING */ + { 24, -4 }, /* (24) phrase ::= phrase PLUS STRING star_opt */ + { 24, -2 }, /* (25) phrase ::= STRING star_opt */ + { 26, -1 }, /* (26) star_opt ::= STAR */ + { 26, 0 }, /* (27) star_opt ::= */ }; static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ @@ -186074,22 +192486,39 @@ static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. +** +** The fts5yyLookahead and fts5yyLookaheadToken parameters provide reduce actions +** access to the lookahead token (if any). The fts5yyLookahead will be fts5YYNOCODE +** if the lookahead token has already been consumed. As this procedure is +** only called from one place, optimizing compilers will in-line it, which +** means that the extra parameters have no performance impact. */ -static void fts5yy_reduce( +static fts5YYACTIONTYPE fts5yy_reduce( fts5yyParser *fts5yypParser, /* The parser */ - unsigned int fts5yyruleno /* Number of the rule by which to reduce */ + unsigned int fts5yyruleno, /* Number of the rule by which to reduce */ + int fts5yyLookahead, /* Lookahead token, or fts5YYNOCODE if none */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyLookaheadToken /* Value of the lookahead token */ + sqlite3Fts5ParserCTX_PDECL /* %extra_context */ ){ int fts5yygoto; /* The next state */ int fts5yyact; /* The next action */ fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */ int fts5yysize; /* Amount to pop the stack */ - sqlite3Fts5ParserARG_FETCH; + sqlite3Fts5ParserARG_FETCH + (void)fts5yyLookahead; + (void)fts5yyLookaheadToken; fts5yymsp = fts5yypParser->fts5yytos; #ifndef NDEBUG if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; - fprintf(fts5yyTraceFILE, "%sReduce [%s], go to state %d.\n", fts5yyTracePrompt, - fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); + if( fts5yysize ){ + fprintf(fts5yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + fts5yyTracePrompt, + fts5yyruleno, fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); + }else{ + fprintf(fts5yyTraceFILE, "%sReduce %d [%s].\n", + fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno]); + } } #endif /* NDEBUG */ @@ -186106,13 +192535,19 @@ static void fts5yy_reduce( #if fts5YYSTACKDEPTH>0 if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ fts5yyStackOverflow(fts5yypParser); - return; + /* The call to fts5yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } #else if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ if( fts5yyGrowStack(fts5yypParser) ){ fts5yyStackOverflow(fts5yypParser); - return; + /* The call to fts5yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } fts5yymsp = fts5yypParser->fts5yytos; } @@ -186220,7 +192655,13 @@ static void fts5yy_reduce( { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 18: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + case 18: /* nearset ::= CARET phrase */ +{ + sqlite3Fts5ParseSetCaret(fts5yymsp[0].minor.fts5yy53); + fts5yymsp[-1].minor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); +} + break; + case 19: /* nearset ::= STRING LP nearphrases neardist_opt RP */ { sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); @@ -186228,40 +192669,40 @@ static void fts5yy_reduce( } fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 19: /* nearphrases ::= phrase */ + case 20: /* nearphrases ::= phrase */ { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 20: /* nearphrases ::= nearphrases phrase */ + case 21: /* nearphrases ::= nearphrases phrase */ { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 21: /* neardist_opt ::= */ + case 22: /* neardist_opt ::= */ { fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } break; - case 22: /* neardist_opt ::= COMMA STRING */ + case 23: /* neardist_opt ::= COMMA STRING */ { fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } break; - case 23: /* phrase ::= phrase PLUS STRING star_opt */ + case 24: /* phrase ::= phrase PLUS STRING star_opt */ { fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 24: /* phrase ::= STRING star_opt */ + case 25: /* phrase ::= STRING star_opt */ { fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 25: /* star_opt ::= STAR */ + case 26: /* star_opt ::= STAR */ { fts5yymsp[0].minor.fts5yy4 = 1; } break; - case 26: /* star_opt ::= */ + case 27: /* star_opt ::= */ { fts5yymsp[1].minor.fts5yy4 = 0; } break; default: @@ -186280,16 +192721,12 @@ static void fts5yy_reduce( /* It is not possible for a REDUCE to be followed by an error */ assert( fts5yyact!=fts5YY_ERROR_ACTION ); - if( fts5yyact==fts5YY_ACCEPT_ACTION ){ - fts5yypParser->fts5yytos += fts5yysize; - fts5yy_accept(fts5yypParser); - }else{ - fts5yymsp += fts5yysize+1; - fts5yypParser->fts5yytos = fts5yymsp; - fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; - fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; - fts5yyTraceShift(fts5yypParser, fts5yyact); - } + fts5yymsp += fts5yysize+1; + fts5yypParser->fts5yytos = fts5yymsp; + fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; + fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; + fts5yyTraceShift(fts5yypParser, fts5yyact, "... then shift"); + return fts5yyact; } /* @@ -186299,7 +192736,8 @@ static void fts5yy_reduce( static void fts5yy_parse_failed( fts5yyParser *fts5yypParser /* The parser */ ){ - sqlite3Fts5ParserARG_FETCH; + sqlite3Fts5ParserARG_FETCH + sqlite3Fts5ParserCTX_FETCH #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sFail!\n",fts5yyTracePrompt); @@ -186310,7 +192748,8 @@ static void fts5yy_parse_failed( ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserCTX_STORE } #endif /* fts5YYNOERRORRECOVERY */ @@ -186322,7 +192761,8 @@ static void fts5yy_syntax_error( int fts5yymajor, /* The major type of the error token */ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyminor /* The minor type of the error token */ ){ - sqlite3Fts5ParserARG_FETCH; + sqlite3Fts5ParserARG_FETCH + sqlite3Fts5ParserCTX_FETCH #define FTS5TOKEN fts5yyminor /************ Begin %syntax_error code ****************************************/ @@ -186331,7 +192771,8 @@ static void fts5yy_syntax_error( pParse, "fts5: syntax error near \"%.*s\"",FTS5TOKEN.n,FTS5TOKEN.p ); /************ End %syntax_error code ******************************************/ - sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserCTX_STORE } /* @@ -186340,7 +192781,8 @@ static void fts5yy_syntax_error( static void fts5yy_accept( fts5yyParser *fts5yypParser /* The parser */ ){ - sqlite3Fts5ParserARG_FETCH; + sqlite3Fts5ParserARG_FETCH + sqlite3Fts5ParserCTX_FETCH #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sAccept!\n",fts5yyTracePrompt); @@ -186354,7 +192796,8 @@ static void fts5yy_accept( ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ /*********** End %parse_accept code *******************************************/ - sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ + sqlite3Fts5ParserCTX_STORE } /* The main parser program. @@ -186383,38 +192826,51 @@ static void sqlite3Fts5Parser( sqlite3Fts5ParserARG_PDECL /* Optional %extra_argument parameter */ ){ fts5YYMINORTYPE fts5yyminorunion; - unsigned int fts5yyact; /* The parser action. */ + fts5YYACTIONTYPE fts5yyact; /* The parser action. */ #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) int fts5yyendofinput; /* True if we are at the end of input */ #endif #ifdef fts5YYERRORSYMBOL int fts5yyerrorhit = 0; /* True if fts5yymajor has invoked an error */ #endif - fts5yyParser *fts5yypParser; /* The parser */ + fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yyp; /* The parser */ + sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_STORE - fts5yypParser = (fts5yyParser*)fts5yyp; assert( fts5yypParser->fts5yytos!=0 ); #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) fts5yyendofinput = (fts5yymajor==0); #endif - sqlite3Fts5ParserARG_STORE; + fts5yyact = fts5yypParser->fts5yytos->stateno; #ifndef NDEBUG if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sInput '%s'\n",fts5yyTracePrompt,fts5yyTokenName[fts5yymajor]); + if( fts5yyact < fts5YY_MIN_REDUCE ){ + fprintf(fts5yyTraceFILE,"%sInput '%s' in state %d\n", + fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact); + }else{ + fprintf(fts5yyTraceFILE,"%sInput '%s' with pending reduce %d\n", + fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact-fts5YY_MIN_REDUCE); + } } #endif do{ - fts5yyact = fts5yy_find_shift_action(fts5yypParser,(fts5YYCODETYPE)fts5yymajor); - if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ + assert( fts5yyact==fts5yypParser->fts5yytos->stateno ); + fts5yyact = fts5yy_find_shift_action(fts5yymajor,fts5yyact); + if( fts5yyact >= fts5YY_MIN_REDUCE ){ + fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor, + fts5yyminor sqlite3Fts5ParserCTX_PARAM); + }else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor); #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt--; #endif - fts5yymajor = fts5YYNOCODE; - }else if( fts5yyact <= fts5YY_MAX_REDUCE ){ - fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE); + break; + }else if( fts5yyact==fts5YY_ACCEPT_ACTION ){ + fts5yypParser->fts5yytos--; + fts5yy_accept(fts5yypParser); + return; }else{ assert( fts5yyact == fts5YY_ERROR_ACTION ); fts5yyminorunion.fts5yy0 = fts5yyminor; @@ -186481,6 +192937,8 @@ static void sqlite3Fts5Parser( } fts5yypParser->fts5yyerrcnt = 3; fts5yyerrorhit = 1; + if( fts5yymajor==fts5YYNOCODE ) break; + fts5yyact = fts5yypParser->fts5yytos->stateno; #elif defined(fts5YYNOERRORRECOVERY) /* If the fts5YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax @@ -186491,8 +192949,7 @@ static void sqlite3Fts5Parser( */ fts5yy_syntax_error(fts5yypParser,fts5yymajor, fts5yyminor); fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); - fts5yymajor = fts5YYNOCODE; - + break; #else /* fts5YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -186514,10 +192971,10 @@ static void sqlite3Fts5Parser( fts5yypParser->fts5yyerrcnt = -1; #endif } - fts5yymajor = fts5YYNOCODE; + break; #endif } - }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); + }while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); #ifndef NDEBUG if( fts5yyTraceFILE ){ fts5yyStackEntry *i; @@ -186893,6 +193350,16 @@ static int fts5SnippetScore( return rc; } +/* +** Return the value in pVal interpreted as utf-8 text. Except, if pVal +** contains a NULL value, return a pointer to a static string zero +** bytes in length instead of a NULL pointer. +*/ +static const char *fts5ValueToText(sqlite3_value *pVal){ + const char *zRet = (const char*)sqlite3_value_text(pVal); + return zRet ? zRet : ""; +} + /* ** Implementation of snippet() function. */ @@ -186928,9 +193395,9 @@ static void fts5SnippetFunction( nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); - ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); - ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); - zEllips = (const char*)sqlite3_value_text(apVal[3]); + ctx.zOpen = fts5ValueToText(apVal[1]); + ctx.zClose = fts5ValueToText(apVal[2]); + zEllips = fts5ValueToText(apVal[3]); nToken = sqlite3_value_int(apVal[4]); iBestCol = (iCol>=0 ? iCol : 0); @@ -188684,7 +195151,8 @@ struct Fts5ExprNode { ** or term prefix. */ struct Fts5ExprTerm { - int bPrefix; /* True for a prefix term */ + u8 bPrefix; /* True for a prefix term */ + u8 bFirst; /* True if token must be first in column */ char *zTerm; /* nul-terminated term */ Fts5IndexIter *pIter; /* Iterator for this term */ Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */ @@ -188765,6 +195233,7 @@ static int fts5ExprGetToken( case '+': tok = FTS5_PLUS; break; case '*': tok = FTS5_STAR; break; case '-': tok = FTS5_MINUS; break; + case '^': tok = FTS5_CARET; break; case '\0': tok = FTS5_EOF; break; case '"': { @@ -189024,6 +195493,7 @@ static int fts5ExprPhraseIsMatch( Fts5PoslistReader *aIter = aStatic; int i; int rc = SQLITE_OK; + int bFirst = pPhrase->aTerm[0].bFirst; fts5BufferZero(&pPhrase->poslist); @@ -189078,8 +195548,10 @@ static int fts5ExprPhraseIsMatch( }while( bMatch==0 ); /* Append position iPos to the output */ - rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); - if( rc!=SQLITE_OK ) goto ismatch_out; + if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){ + rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); + if( rc!=SQLITE_OK ) goto ismatch_out; + } for(i=0; inTerm; i++){ if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; @@ -189333,7 +195805,9 @@ static int fts5ExprNearTest( ** phrase is not a match, break out of the loop early. */ for(i=0; rc==SQLITE_OK && inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ + if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym + || pNear->pColset || pPhrase->aTerm[0].bFirst + ){ int bMatch = 0; rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); if( bMatch==0 ) break; @@ -189514,6 +195988,7 @@ static int fts5ExprNodeTest_STRING( assert( pNear->nPhrase>1 || pNear->apPhrase[0]->nTerm>1 || pNear->apPhrase[0]->aTerm[0].pSynonym + || pNear->apPhrase[0]->aTerm[0].bFirst ); /* Initialize iLast, the "lastest" rowid any iterator points to. If the @@ -190038,6 +196513,16 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){ } } +/* +** Set the "bFirst" flag on the first token of the phrase passed as the +** only argument. +*/ +static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){ + if( pPhrase && pPhrase->nTerm ){ + pPhrase->aTerm[0].bFirst = 1; + } +} + /* ** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated ** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is @@ -190255,7 +196740,7 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm( ** no token characters at all. (e.g ... MATCH '""'). */ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase)); }else if( sCtx.pPhrase->nTerm ){ - sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; + sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix; } pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; } @@ -190316,6 +196801,7 @@ static int sqlite3Fts5ExprClonePhrase( } if( rc==SQLITE_OK ){ sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; } } }else{ @@ -190334,7 +196820,10 @@ static int sqlite3Fts5ExprClonePhrase( pNew->pRoot->pNear->nPhrase = 1; sCtx.pPhrase->pNode = pNew->pRoot; - if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ + if( pOrig->nTerm==1 + && pOrig->aTerm[0].pSynonym==0 + && pOrig->aTerm[0].bFirst==0 + ){ pNew->pRoot->eType = FTS5_TERM; pNew->pRoot->xNext = fts5ExprNodeNext_TERM; }else{ @@ -190608,6 +197097,7 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ Fts5ExprNearset *pNear = pNode->pNear; if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 && pNear->apPhrase[0]->aTerm[0].pSynonym==0 + && pNear->apPhrase[0]->aTerm[0].bFirst==0 ){ pNode->eType = FTS5_TERM; pNode->xNext = fts5ExprNodeNext_TERM; @@ -190694,20 +197184,23 @@ static Fts5ExprNode *sqlite3Fts5ParseNode( } } - if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL - && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1) - ){ - assert( pParse->rc==SQLITE_OK ); - pParse->rc = SQLITE_ERROR; - assert( pParse->zErr==0 ); - pParse->zErr = sqlite3_mprintf( - "fts5: %s queries are not supported (detail!=full)", - pNear->nPhrase==1 ? "phrase": "NEAR" - ); - sqlite3_free(pRet); - pRet = 0; + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; + if( pNear->nPhrase!=1 + || pPhrase->nTerm>1 + || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst) + ){ + assert( pParse->rc==SQLITE_OK ); + pParse->rc = SQLITE_ERROR; + assert( pParse->zErr==0 ); + pParse->zErr = sqlite3_mprintf( + "fts5: %s queries are not supported (detail!=full)", + pNear->nPhrase==1 ? "phrase": "NEAR" + ); + sqlite3_free(pRet); + pRet = 0; + } } - }else{ fts5ExprAddChildren(pRet, pLeft); fts5ExprAddChildren(pRet, pRight); @@ -192710,6 +199203,7 @@ static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){ sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC); sqlite3_step(p->pWriter); p->rc = sqlite3_reset(p->pWriter); + sqlite3_bind_null(p->pWriter, 2); } /* @@ -194338,6 +200832,7 @@ static void fts5SegIterSeekInit( bDlidx = (val & 0x0001); } p->rc = sqlite3_reset(pIdxSelect); + sqlite3_bind_null(pIdxSelect, 2); if( iPgpgnoFirst ){ iPg = pSeg->pgnoFirst; @@ -195550,6 +202045,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); p->rc = sqlite3_reset(pIdxSelect); + sqlite3_bind_null(pIdxSelect, 2); } } #endif @@ -195676,6 +202172,7 @@ static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){ sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1)); sqlite3_step(p->pIdxWriter); p->rc = sqlite3_reset(p->pIdxWriter); + sqlite3_bind_null(p->pIdxWriter, 2); } pWriter->iBtPage = 0; } @@ -196861,7 +203358,13 @@ static void fts5MergePrefixLists( Fts5Buffer out = {0, 0, 0}; Fts5Buffer tmp = {0, 0, 0}; - if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; + /* The maximum size of the output is equal to the sum of the two + ** input sizes + 1 varint (9 bytes). The extra varint is because if the + ** first rowid in one input is a large negative number, and the first in + ** the other a non-negative number, the delta for the non-negative + ** number will be larger on disk than the literal integer value + ** was. */ + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return; fts5DoclistIterInit(p1, &i1); fts5DoclistIterInit(p2, &i2); @@ -196955,6 +203458,7 @@ static void fts5MergePrefixLists( fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); } + assert( out.n<=(p1->n+p2->n+9) ); fts5BufferSet(&p->rc, p1, out.n, out.p); fts5BufferFree(&tmp); @@ -198982,6 +205486,12 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ aColMap[1] = nCol; aColMap[2] = nCol+1; + assert( SQLITE_INDEX_CONSTRAINT_EQnConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; @@ -199000,11 +205510,11 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ pInfo->estimatedCost = 1e50; return SQLITE_OK; } - }else{ + }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){ int j; for(j=1; jiCol] && p->op & pC->op && p->usable ){ + if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){ pC->iConsIndex = i; idxFlags |= pC->fts5op; } @@ -201076,7 +207586,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ @@ -201652,6 +208162,7 @@ static int fts5StorageInsertDocsize( sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 2); } } return rc; @@ -202312,6 +208823,7 @@ static int sqlite3Fts5StorageConfigValue( } sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 1); } if( rc==SQLITE_OK && pVal ){ int iNew = p->pConfig->iCookie + 1; @@ -205344,9 +211856,9 @@ SQLITE_API int sqlite3_stmt_init( #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=205346 +#if __LINE__!=211858 #undef SQLITE_SOURCE_ID -#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de4alt2" +#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199aalt2" #endif /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } @@ -205354,4 +211866,359 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #else // USE_LIBSQLITE3 // If users really want to link against the system sqlite3 we // need to make this file a noop. - #endif \ No newline at end of file + #endif +/* +** 2014-09-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the bulk of the implementation of the +** user-authentication extension feature. Some parts of the user- +** authentication code are contained within the SQLite core (in the +** src/ subdirectory of the main source code tree) but those parts +** that could reasonable be separated out are moved into this file. +** +** To compile with the user-authentication feature, append this file to +** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION +** compile-time option. See the user-auth.txt file in the same source +** directory as this file for additional information. +*/ +#ifdef SQLITE_USER_AUTHENTICATION +#ifndef SQLITEINT_H +# include "sqliteInt.h" +#endif + +/* +** Prepare an SQL statement for use by the user authentication logic. +** Return a pointer to the prepared statement on success. Return a +** NULL pointer if there is an error of any kind. +*/ +static sqlite3_stmt *sqlite3UserAuthPrepare( + sqlite3 *db, + const char *zFormat, + ... +){ + sqlite3_stmt *pStmt; + char *zSql; + int rc; + va_list ap; + int savedFlags = db->flags; + + va_start(ap, zFormat); + zSql = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + if( zSql==0 ) return 0; + db->flags |= SQLITE_WriteSchema; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + db->flags = savedFlags; + sqlite3_free(zSql); + if( rc ){ + sqlite3_finalize(pStmt); + pStmt = 0; + } + return pStmt; +} + +/* +** Check to see if the sqlite_user table exists in database zDb. +*/ +static int userTableExists(sqlite3 *db, const char *zDb){ + int rc; + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + if( db->init.busy==0 ){ + char *zErr = 0; + sqlite3Init(db, &zErr); + sqlite3DbFree(db, zErr); + } + rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0; + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Check to see if database zDb has a "sqlite_user" table and if it does +** whether that table can authenticate zUser with nPw,zPw. Write one of +** the UAUTH_* user authorization level codes into *peAuth and return a +** result code. +*/ +static int userAuthCheckLogin( + sqlite3 *db, /* The database connection to check */ + const char *zDb, /* Name of specific database to check */ + u8 *peAuth /* OUT: One of UAUTH_* constants */ +){ + sqlite3_stmt *pStmt; + int rc; + + *peAuth = UAUTH_Unknown; + if( !userTableExists(db, "main") ){ + *peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */ + return SQLITE_OK; + } + if( db->auth.zAuthUser==0 ){ + *peAuth = UAUTH_Fail; + return SQLITE_OK; + } + pStmt = sqlite3UserAuthPrepare(db, + "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user" + " WHERE uname=?2", zDb); + if( pStmt==0 ) return SQLITE_NOMEM; + sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC); + sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC); + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){ + *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User; + }else{ + *peAuth = UAUTH_Fail; + } + return sqlite3_finalize(pStmt); +} +int sqlite3UserAuthCheckLogin( + sqlite3 *db, /* The database connection to check */ + const char *zDb, /* Name of specific database to check */ + u8 *peAuth /* OUT: One of UAUTH_* constants */ +){ + int rc; + u8 savedAuthLevel; + assert( zDb!=0 ); + assert( peAuth!=0 ); + savedAuthLevel = db->auth.authLevel; + db->auth.authLevel = UAUTH_Admin; + rc = userAuthCheckLogin(db, zDb, peAuth); + db->auth.authLevel = savedAuthLevel; + return rc; +} + +/* +** If the current authLevel is UAUTH_Unknown, the take actions to figure +** out what authLevel should be +*/ +void sqlite3UserAuthInit(sqlite3 *db){ + if( db->auth.authLevel==UAUTH_Unknown ){ + u8 authLevel = UAUTH_Fail; + sqlite3UserAuthCheckLogin(db, "main", &authLevel); + db->auth.authLevel = authLevel; + if( authLevelflags &= ~SQLITE_WriteSchema; + } +} + +/* +** Implementation of the sqlite_crypt(X,Y) function. +** +** If Y is NULL then generate a new hash for password X and return that +** hash. If Y is not null, then generate a hash for password X using the +** same salt as the previous hash Y and return the new hash. +*/ +void sqlite3CryptFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + const char *zIn; + int nIn, ii; + u8 *zOut; + char zSalt[8]; + zIn = sqlite3_value_blob(argv[0]); + nIn = sqlite3_value_bytes(argv[0]); + if( sqlite3_value_type(argv[1])==SQLITE_BLOB + && sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt) + ){ + memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt)); + }else{ + sqlite3_randomness(sizeof(zSalt), zSalt); + } + zOut = sqlite3_malloc( nIn+sizeof(zSalt) ); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + }else{ + memcpy(zOut, zSalt, sizeof(zSalt)); + for(ii=0; iiauth.authLevel = UAUTH_Unknown; + sqlite3_free(db->auth.zAuthUser); + sqlite3_free(db->auth.zAuthPW); + memset(&db->auth, 0, sizeof(db->auth)); + db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername); + if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM; + db->auth.zAuthPW = sqlite3_malloc( nPW+1 ); + if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM; + memcpy(db->auth.zAuthPW,zPW,nPW); + db->auth.nAuthPW = nPW; + rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel); + db->auth.authLevel = authLevel; + sqlite3ExpirePreparedStatements(db); + if( rc ){ + return rc; /* OOM error, I/O error, etc. */ + } + if( authLevelauth.authLevelauth.zAuthUser==0 ){ + assert( isAdmin!=0 ); + sqlite3_user_authenticate(db, zUsername, aPW, nPW); + } + return SQLITE_OK; +} + +/* +** The sqlite3_user_change() interface can be used to change a users +** login credentials or admin privilege. Any user can change their own +** login credentials. Only an admin user can change another users login +** credentials or admin privilege setting. No user may change their own +** admin privilege setting. +*/ +int sqlite3_user_change( + sqlite3 *db, /* Database connection */ + const char *zUsername, /* Username to change */ + const char *aPW, /* Modified password or credentials */ + int nPW, /* Number of bytes in aPW[] */ + int isAdmin /* Modified admin privilege for the user */ +){ + sqlite3_stmt *pStmt; + int rc; + u8 authLevel; + + authLevel = db->auth.authLevel; + if( authLevelauth.zAuthUser, zUsername)!=0 ){ + if( db->auth.authLevelauth.authLevel = UAUTH_Admin; + if( !userTableExists(db, "main") ){ + /* This routine is a no-op if the user to be modified does not exist */ + }else{ + pStmt = sqlite3UserAuthPrepare(db, + "UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)" + " WHERE uname=%Q", isAdmin, zUsername); + if( pStmt==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC); + sqlite3_step(pStmt); + rc = sqlite3_finalize(pStmt); + } + } + db->auth.authLevel = authLevel; + return rc; +} + +/* +** The sqlite3_user_delete() interface can be used (by an admin user only) +** to delete a user. The currently logged-in user cannot be deleted, +** which guarantees that there is always an admin user and hence that +** the database cannot be converted into a no-authentication-required +** database. +*/ +int sqlite3_user_delete( + sqlite3 *db, /* Database connection */ + const char *zUsername /* Username to remove */ +){ + sqlite3_stmt *pStmt; + if( db->auth.authLevelauth.zAuthUser, zUsername)==0 ){ + /* Cannot delete self */ + return SQLITE_AUTH; + } + if( !userTableExists(db, "main") ){ + /* This routine is a no-op if the user to be deleted does not exist */ + return SQLITE_OK; + } + pStmt = sqlite3UserAuthPrepare(db, + "DELETE FROM sqlite_user WHERE uname=%Q", zUsername); + if( pStmt==0 ) return SQLITE_NOMEM; + sqlite3_step(pStmt); + return sqlite3_finalize(pStmt); +} + +#endif /* SQLITE_USER_AUTHENTICATION */ diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h index 76a7287..4bf489a 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h @@ -124,9 +124,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.21.0" -#define SQLITE_VERSION_NUMBER 3021000 -#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827" +#define SQLITE_VERSION "3.24.0" +#define SQLITE_VERSION_NUMBER 3024000 +#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -471,6 +471,8 @@ SQLITE_API int sqlite3_exec( ** the most recent error can be obtained using ** [sqlite3_extended_errcode()]. */ +#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) +#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) @@ -503,6 +505,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) @@ -510,10 +513,13 @@ SQLITE_API int sqlite3_exec( #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) +#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) +#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) @@ -1061,6 +1067,12 @@ struct sqlite3_io_methods { ** so that all subsequent write operations are independent. ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain +** a file lock using the xLock or xShmLock methods of the VFS to wait +** for up to M milliseconds before failing, where M is the single +** unsigned integer parameter. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1095,6 +1107,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1132,12 +1145,18 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. ** -** The value of the iVersion field is initially 1 but may be larger in -** future versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. Note that the structure -** of the sqlite3_vfs object changes in the transaction between -** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not -** modified. +** The VFS interface is sometimes extended by adding new methods onto +** the end. Each time such an extension occurs, the iVersion field +** is incremented. The iVersion value started out as 1 in +** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 +** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased +** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields +** may be appended to the sqlite3_vfs object and the iVersion value +** may increase again in future versions of SQLite. +** Note that the structure +** of the sqlite3_vfs object changes in the transition from +** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] +** and yet the iVersion field was not modified. ** ** The szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of @@ -1914,6 +1933,22 @@ struct sqlite3_mem_methods { ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. +** +** [[SQLITE_CONFIG_SORTERREF_SIZE]] +**
    SQLITE_CONFIG_SORTERREF_SIZE +**
    The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter +** of type (int) - the new value of the sorter-reference size threshold. +** Usually, when SQLite uses an external sort to order records according +** to an ORDER BY clause, all fields required by the caller are present in the +** sorted records. However, if SQLite determines based on the declared type +** of a table column that its values are likely to be very large - larger +** than the configured sorter-reference size threshold - then a reference +** is stored in each sorted record and the required column values loaded +** from the database as records are returned in sorted order. The default +** value for this option is to never use this optimization. Specifying a +** negative value for this option restores the default behaviour. +** This option is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -1943,6 +1978,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ +#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2045,8 +2081,9 @@ struct sqlite3_mem_methods { ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to ** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer +** is an integer - positive to disable checkpoints-on-close, or zero (the +** default) to enable them, and negative to leave the setting unchanged. +** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. **
    @@ -2060,8 +2097,39 @@ struct sqlite3_mem_methods { ** slower. But the QPSG has the advantage of more predictable behavior. With ** the QPSG active, SQLite will always use the same query plan in the field as ** was used during testing in the lab. +** The first argument to this setting is an integer which is 0 to disable +** the QPSG, positive to enable QPSG, or negative to leave the setting +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether the QPSG is disabled or enabled +** following this call. ** ** +**
    SQLITE_DBCONFIG_TRIGGER_EQP
    +**
    By default, the output of EXPLAIN QUERY PLAN commands does not +** include output for any operations performed by trigger programs. This +** option is used to set or clear (the default) a flag that governs this +** behavior. The first parameter passed to this operation is an integer - +** positive to enable output for trigger programs, or zero to disable it, +** or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which is written +** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if +** it is not disabled, 1 if it is. +**
    +** +**
    SQLITE_DBCONFIG_RESET_DATABASE
    +**
    Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run +** [VACUUM] in order to reset a database back to an empty database +** with no schema and no content. The following process works even for +** a badly corrupted database file: +**
      +**
    1. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); +**
    2. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); +**
    3. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); +**
    +** Because resetting a database is destructive and irreversible, the +** process requires the use of this obscure API and multiple steps to help +** ensure that it does not happen by accident. +**
    ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2072,7 +2140,9 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ - +#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ +#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -2478,16 +2548,16 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. -** These routines understand most of the common K&R formatting options, -** plus some additional non-standard formats, detailed below. -** Note that some of the more obscure formatting options from recent -** C-library standards are omitted from this implementation. +** These routines understand most of the common formatting options from +** the standard library printf() +** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). +** See the [built-in printf()] documentation for details. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. +** results into memory obtained from [sqlite3_malloc64()]. ** The strings returned by these two routines should be ** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough ** memory to hold the resulting string. ** ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from @@ -2511,71 +2581,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). ** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", "%w" and "%z" options. -** -** ^(The %q option works like %s in that it substitutes a nul-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal.)^ By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, assume the string variable zText contains text as follows: -** -**
    -**  char *zText = "It's a happy day!";
    -** 
    -** -** One can use this text in an SQL statement as follows: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
    -**  INSERT INTO table1 VALUES('It''s a happy day!')
    -** 
    -** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
    -**  INSERT INTO table1 VALUES('It's a happy day!');
    -** 
    -** -** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. -** -** ^(The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Additionally, if the parameter in the -** argument list is a NULL pointer, %Q substitutes the text "NULL" (without -** single quotes).)^ So, for example, one could say: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** ^(The "%w" formatting option is like "%q" except that it expects to -** be contained within double-quotes instead of single quotes, and it -** escapes the double-quote character instead of the single-quote -** character.)^ The "%w" formatting option is intended for safely inserting -** table and column names into a constructed SQL statement. -** -** ^(The "%z" formatting option works like "%s" but with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string.)^ +** See also: [built-in printf()], [printf() SQL function] */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); @@ -2933,8 +2939,8 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** KEYWORDS: SQLITE_TRACE ** ** These constants identify classes of events that can be monitored -** using the [sqlite3_trace_v2()] tracing logic. The third argument -** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of +** using the [sqlite3_trace_v2()] tracing logic. The M argument +** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of ** the following constants. ^The first argument to the trace callback ** is one of the following constants. ** @@ -3641,13 +3647,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. **
  • +** ** **

    ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ** the extra prepFlags parameter, which is a bit array consisting of zero or ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The ** sqlite3_prepare_v2() interface works exactly the same as ** sqlite3_prepare_v3() with a zero prepFlags parameter. -** */ SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ @@ -4780,6 +4786,9 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** datatype of the value **

    sqlite3_value_numeric_type   ** →  Best numeric datatype of the value +**
    sqlite3_value_nochange   +** →  True if the column is unchanged in an UPDATE +** against a virtual table. **
    ** ** Details: @@ -4828,6 +4837,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** +** ^Within the [xUpdate] method of a [virtual table], the +** sqlite3_value_nochange(X) interface returns true if and only if +** the column corresponding to X is unchanged by the UPDATE operation +** that the xUpdate method call was invoked to implement and if +** and the prior [xColumn] method call that was invoked to extracted +** the value for that column returned without setting a result (probably +** because it queried [sqlite3_vtab_nochange()] and found that the column +** was unchanging). ^Within an [xUpdate] method, any value for which +** sqlite3_value_nochange(X) is true will in all other respects appear +** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other +** than within an [xUpdate] method call for an UPDATE statement, then +** the return value is arbitrary and meaningless. +** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to @@ -4850,6 +4872,7 @@ SQLITE_API int sqlite3_value_bytes(sqlite3_value*); SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API int sqlite3_value_nochange(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -5505,6 +5528,41 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; */ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; +/* +** CAPI3REF: Win32 Specific Interface +** +** These interfaces are available only on Windows. The +** [sqlite3_win32_set_directory] interface is used to set the value associated +** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to +** zValue, depending on the value of the type parameter. The zValue parameter +** should be NULL to cause the previous value to be freed via [sqlite3_free]; +** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] +** prior to being used. The [sqlite3_win32_set_directory] interface returns +** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, +** or [SQLITE_NOMEM] if memory could not be allocated. The value of the +** [sqlite3_data_directory] variable is intended to act as a replacement for +** the current directory on the sub-platforms of Win32 where that concept is +** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and +** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the +** sqlite3_win32_set_directory interface except the string parameter must be +** UTF-8 or UTF-16, respectively. +*/ +SQLITE_API int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +); +SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); +SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); + +/* +** CAPI3REF: Win32 Directory Types +** +** These macros are only available on Windows. They define the allowed values +** for the type argument to the [sqlite3_win32_set_directory] interface. +*/ +#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 +#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 + /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} @@ -6237,6 +6295,10 @@ struct sqlite3_index_info { /* ** CAPI3REF: Virtual Table Scan Flags +** +** Virtual table implementations are allowed to set the +** [sqlite3_index_info].idxFlags field to some combination of +** these bits. */ #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ @@ -6952,9 +7014,9 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** -** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes ** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] ** case is a short-circuit path which does not actually invoke the ** underlying sqlite3_io_methods.xFileControl method. ** @@ -6966,7 +7028,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** -** See also: [SQLITE_FCNTL_LOCKSTATE] +** See also: [file control opcodes] */ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); @@ -7012,7 +7074,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ @@ -7023,7 +7085,191 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 +#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 +#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + +/* +** CAPI3REF: SQL Keyword Checking +** +** These routines provide access to the set of SQL language keywords +** recognized by SQLite. Applications can uses these routines to determine +** whether or not a specific identifier needs to be escaped (for example, +** by enclosing in double-quotes) so as not to confuse the parser. +** +** The sqlite3_keyword_count() interface returns the number of distinct +** keywords understood by SQLite. +** +** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** makes *Z point to that keyword expressed as UTF8 and writes the number +** of bytes in the keyword into *L. The string that *Z points to is not +** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns +** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z +** or L are NULL or invalid pointers then calls to +** sqlite3_keyword_name(N,Z,L) result in undefined behavior. +** +** The sqlite3_keyword_check(Z,L) interface checks to see whether or not +** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero +** if it is and zero if not. +** +** The parser used by SQLite is forgiving. It is often possible to use +** a keyword as an identifier as long as such use does not result in a +** parsing ambiguity. For example, the statement +** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and +** creates a new table named "BEGIN" with three columns named +** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid +** using keywords as identifiers. Common techniques used to avoid keyword +** name collisions include: +**
      +**
    • Put all identifier names inside double-quotes. This is the official +** SQL way to escape identifier names. +**
    • Put identifier names inside [...]. This is not standard SQL, +** but it is what SQL Server does and so lots of programmers use this +** technique. +**
    • Begin every identifier with the letter "Z" as no SQL keywords start +** with "Z". +**
    • Include a digit somewhere in every identifier name. +**
    +** +** Note that the number of keywords understood by SQLite can depend on +** compile-time options. For example, "VACUUM" is not a keyword if +** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, +** new keywords may be added to future releases of SQLite. +*/ +SQLITE_API int sqlite3_keyword_count(void); +SQLITE_API int sqlite3_keyword_name(int,const char**,int*); +SQLITE_API int sqlite3_keyword_check(const char*,int); + +/* +** CAPI3REF: Dynamic String Object +** KEYWORDS: {dynamic string} +** +** An instance of the sqlite3_str object contains a dynamically-sized +** string under construction. +** +** The lifecycle of an sqlite3_str object is as follows: +**
      +**
    1. ^The sqlite3_str object is created using [sqlite3_str_new()]. +**
    2. ^Text is appended to the sqlite3_str object using various +** methods, such as [sqlite3_str_appendf()]. +**
    3. ^The sqlite3_str object is destroyed and the string it created +** is returned using the [sqlite3_str_finish()] interface. +**
    +*/ +typedef struct sqlite3_str sqlite3_str; + +/* +** CAPI3REF: Create A New Dynamic String Object +** CONSTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_new(D)] interface allocates and initializes +** a new [sqlite3_str] object. To avoid memory leaks, the object returned by +** [sqlite3_str_new()] must be freed by a subsequent call to +** [sqlite3_str_finish(X)]. +** +** ^The [sqlite3_str_new(D)] interface always returns a pointer to a +** valid [sqlite3_str] object, though in the event of an out-of-memory +** error the returned object might be a special singleton that will +** silently reject new text, always return SQLITE_NOMEM from +** [sqlite3_str_errcode()], always return 0 for +** [sqlite3_str_length()], and always return NULL from +** [sqlite3_str_finish(X)]. It is always safe to use the value +** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter +** to any of the other [sqlite3_str] methods. +** +** The D parameter to [sqlite3_str_new(D)] may be NULL. If the +** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum +** length of the string contained in the [sqlite3_str] object will be +** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead +** of [SQLITE_MAX_LENGTH]. +*/ +SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); + +/* +** CAPI3REF: Finalize A Dynamic String +** DESTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X +** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] +** that contains the constructed string. The calling application should +** pass the returned value to [sqlite3_free()] to avoid a memory leak. +** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any +** errors were encountered during construction of the string. ^The +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the +** string in [sqlite3_str] object X is zero bytes long. +*/ +SQLITE_API char *sqlite3_str_finish(sqlite3_str*); + +/* +** CAPI3REF: Add Content To A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. +** +** ^The [sqlite3_str_appendf(X,F,...)] and +** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] +** functionality of SQLite to append formatted text onto the end of +** [sqlite3_str] object X. +** +** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S +** onto the end of the [sqlite3_str] object X. N must be non-negative. +** S must contain at least N non-zero bytes of content. To append a +** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] +** method instead. +** +** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of +** zero-terminated string S onto the end of [sqlite3_str] object X. +** +** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the +** single-byte character C onto the end of [sqlite3_str] object X. +** ^This method can be used, for example, to add whitespace indentation. +** +** ^The [sqlite3_str_reset(X)] method resets the string under construction +** inside [sqlite3_str] object X back to zero bytes in length. +** +** These methods do not return a result code. ^If an error occurs, that fact +** is recorded in the [sqlite3_str] object and can be recovered by a +** subsequent call to [sqlite3_str_errcode(X)]. +*/ +SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); +SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); +SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); +SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); +SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); +SQLITE_API void sqlite3_str_reset(sqlite3_str*); + +/* +** CAPI3REF: Status Of A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces return the current status of an [sqlite3_str] object. +** +** ^If any prior errors have occurred while constructing the dynamic string +** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return +** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns +** [SQLITE_NOMEM] following any out-of-memory error, or +** [SQLITE_TOOBIG] if the size of the dynamic string exceeds +** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. +** +** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, +** of the dynamic string under construction in [sqlite3_str] object X. +** ^The length returned by [sqlite3_str_length(X)] does not include the +** zero-termination byte. +** +** ^The [sqlite3_str_value(X)] method returns a pointer to the current +** content of the dynamic string under construction in X. The value +** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X +** and might be freed or altered by any subsequent method on the same +** [sqlite3_str] object. Applications must not used the pointer returned +** [sqlite3_str_value(X)] after any subsequent method call on the same +** object. ^Applications may change the content of the string returned +** by [sqlite3_str_value(X)] as long as they do not write into any bytes +** outside the range of 0 to [sqlite3_str_length(X)] and do not read or +** write any byte after any subsequent sqlite3_str method call. +*/ +SQLITE_API int sqlite3_str_errcode(sqlite3_str*); +SQLITE_API int sqlite3_str_length(sqlite3_str*); +SQLITE_API char *sqlite3_str_value(sqlite3_str*); /* ** CAPI3REF: SQLite Runtime Status @@ -7258,6 +7504,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. **
    ** +** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
    SQLITE_DBSTATUS_CACHE_SPILL
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk in the middle of a transaction due to the page +** cache overflowing. Transactions are more efficient if they are written +** to disk all at once. When pages spill mid-transaction, that introduces +** additional overhead. This parameter can be used help identify +** inefficiencies that can be resolve by increasing the cache size. +**
    +** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    **
    This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been @@ -7277,7 +7532,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_SPILL 12 +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -8277,6 +8533,40 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); */ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); +/* +** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE +** +** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] +** method of a [virtual table], then it returns true if and only if the +** column is being fetched as part of an UPDATE operation during which the +** column value will not change. Applications might use this to substitute +** a return value that is less expensive to compute and that the corresponding +** [xUpdate] method understands as a "no-change" value. +** +** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that +** the column is not changed by the UPDATE statement, then the xColumn +** method can optionally return without setting a result, without calling +** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. +** In that case, [sqlite3_value_nochange(X)] will return true for the +** same column in the [xUpdate] method. +*/ +SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); + +/* +** CAPI3REF: Determine The Collation For a Virtual Table Constraint +** +** This function may only be called from within a call to the [xBestIndex] +** method of a [virtual table]. +** +** The first argument must be the sqlite3_index_info object that is the +** first parameter to the xBestIndex() method. The second argument must be +** an index into the aConstraint[] array belonging to the sqlite3_index_info +** structure passed to xBestIndex. This function returns a pointer to a buffer +** containing the name of the collation sequence for the corresponding +** constraint. +*/ +SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); + /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} @@ -8723,6 +9013,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Serialize a database +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contiguous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Deserialize a database +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnect from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is resposible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database using calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -8870,16 +9282,23 @@ extern "C" { /* ** CAPI3REF: Session Object Handle +** +** An instance of this object is a [session] that can be used to +** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle +** +** An instance of this object acts as a cursor for iterating +** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object +** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is @@ -8916,6 +9335,7 @@ SQLITE_API int sqlite3session_create( /* ** CAPI3REF: Delete A Session Object +** DESTRUCTOR: sqlite3_session ** ** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the @@ -8931,6 +9351,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object +** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When @@ -8950,6 +9371,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag +** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: @@ -8979,6 +9401,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) /* ** CAPI3REF: Attach A Table To A Session Object +** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach ** to the session object passed as the first argument. All subsequent changes @@ -9004,6 +9427,35 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) ** ** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. +** +**

    Special sqlite_stat1 Handling

    +** +** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to +** some of the rules above. In SQLite, the schema of sqlite_stat1 is: +**
    +**        CREATE TABLE sqlite_stat1(tbl,idx,stat)  
    +**  
    +** +** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are +** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes +** are recorded for rows for which (idx IS NULL) is true. However, for such +** rows a zero-length blob (SQL value X'') is stored in the changeset or +** patchset instead of a NULL value. This allows such changesets to be +** manipulated by legacy implementations of sqlite3changeset_invert(), +** concat() and similar. +** +** The sqlite3changeset_apply() function automatically converts the +** zero-length blob back to a NULL value when updating the sqlite_stat1 +** table. However, if the application calls sqlite3changeset_new(), +** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset +** iterator directly (including on a changeset iterator passed to a +** conflict-handler callback) then the X'' value is returned. The application +** must translate X'' to NULL itself if required. +** +** Legacy (older than 3.22.0) versions of the sessions module cannot capture +** changes made to the sqlite_stat1 table. Legacy versions of the +** sqlite3changeset_apply() function silently ignore any modifications to the +** sqlite_stat1 table that are part of a changeset or patchset. */ SQLITE_API int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ @@ -9012,6 +9464,7 @@ SQLITE_API int sqlite3session_attach( /* ** CAPI3REF: Set a table filter on a Session Object. +** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called @@ -9030,6 +9483,7 @@ SQLITE_API void sqlite3session_table_filter( /* ** CAPI3REF: Generate A Changeset From A Session Object +** METHOD: sqlite3_session ** ** Obtain a changeset containing changes to the tables attached to the ** session object passed as the first argument. If successful, @@ -9139,7 +9593,8 @@ SQLITE_API int sqlite3session_changeset( ); /* -** CAPI3REF: Load The Difference Between Tables Into A Session +** CAPI3REF: Load The Difference Between Tables Into A Session +** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the @@ -9204,6 +9659,7 @@ SQLITE_API int sqlite3session_diff( /* ** CAPI3REF: Generate A Patchset From A Session Object +** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** @@ -9255,6 +9711,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset +** CONSTRUCTOR: sqlite3_changeset_iter ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK @@ -9295,6 +9752,7 @@ SQLITE_API int sqlite3changeset_start( /* ** CAPI3REF: Advance A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to @@ -9319,6 +9777,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9353,6 +9812,7 @@ SQLITE_API int sqlite3changeset_op( /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table +** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** @@ -9384,6 +9844,7 @@ SQLITE_API int sqlite3changeset_pk( /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9414,6 +9875,7 @@ SQLITE_API int sqlite3changeset_old( /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9447,6 +9909,7 @@ SQLITE_API int sqlite3changeset_new( /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either @@ -9474,6 +9937,7 @@ SQLITE_API int sqlite3changeset_conflict( /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case @@ -9490,6 +9954,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( /* ** CAPI3REF: Finalize A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. @@ -9506,6 +9971,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** +**
     **   sqlite3changeset_start();
     **   while( SQLITE_ROW==sqlite3changeset_next() ){
     **     // Do something with change.
    @@ -9514,6 +9980,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
     **   if( rc!=SQLITE_OK ){
     **     // An error has occurred 
     **   }
    +** 
    */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); @@ -9561,6 +10028,7 @@ SQLITE_API int sqlite3changeset_invert( ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** +**
     **   sqlite3_changegroup *pGrp;
     **   rc = sqlite3_changegroup_new(&pGrp);
     **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
    @@ -9571,6 +10039,7 @@ SQLITE_API int sqlite3changeset_invert(
     **     *ppOut = 0;
     **     *pnOut = 0;
     **   }
    +** 
    ** ** Refer to the sqlite3_changegroup documentation below for details. */ @@ -9586,11 +10055,15 @@ SQLITE_API int sqlite3changeset_concat( /* ** CAPI3REF: Changegroup Handle +** +** A changegroup is an object used to combine two or more +** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object +** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -9628,6 +10101,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); /* ** CAPI3REF: Add A Changeset To A Changegroup +** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. @@ -9705,6 +10179,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup @@ -9735,25 +10210,25 @@ SQLITE_API int sqlite3changegroup_output( /* ** CAPI3REF: Delete A Changegroup Object +** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset to a database. This function attempts to update the -** "main" database attached to handle db with the changes found in the -** changeset passed via the second and third arguments. +** Apply a changeset or patchset to a database. These functions attempt to +** update the "main" database attached to handle db with the changes found in +** the changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to this function is the "filter +** The fourth argument (xFilter) passed to these functions is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument to this function as the first. If the "filter -** callback" returns zero, then no attempt is made to apply any changes to -** the table. Otherwise, if the return value is non-zero or the xFilter -** argument to this function is NULL, all changes related to the table are -** attempted. +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -9798,7 +10273,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** **
    **
    DELETE Changes
    -** For each DELETE change, this function checks if the target database +** For each DELETE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all non-primary key columns also match the values stored in @@ -9843,7 +10318,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** [SQLITE_CHANGESET_REPLACE]. ** **
    UPDATE Changes
    -** For each UPDATE change, this function checks if the target database +** For each UPDATE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all modified non-primary key columns also match the values @@ -9874,11 +10349,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by this function are enclosed in a savepoint transaction. +** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. +** +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +** may set (*ppRebase) to point to a "rebase" that may be used with the +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +** is set to the size of the buffer in bytes. It is the responsibility of the +** caller to eventually free any such buffer using sqlite3_free(). The buffer +** is only allocated and populated if one or more conflicts were encountered +** while applying the patchset. See comments surrounding the sqlite3_rebaser +** APIs for further details. +** +** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. +** +** Note that the sqlite3changeset_apply_v2() API is still experimental +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -9895,6 +10387,41 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* Combination of SESSION_APPLY_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +** +** The following flags may passed via the 9th parameter to +** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: +** +**
    +**
    SQLITE_CHANGESETAPPLY_NOSAVEPOINT
    +** Usually, the sessions module encloses all operations performed by +** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The +** SAVEPOINT is committed if the changeset or patchset is successfully +** applied, or rolled back if an error occurs. Specifying this flag +** causes the sessions module to omit this savepoint. In this case, if the +** caller has an open transaction or savepoint when apply_v2() is called, +** it may revert the partially applied changeset by rolling it back. +*/ +#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -9992,6 +10519,161 @@ SQLITE_API int sqlite3changeset_apply( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** CAPI3REF: Rebasing changesets +** EXPERIMENTAL +** +** Suppose there is a site hosting a database in state S0. And that +** modifications are made that move that database to state S1 and a +** changeset recorded (the "local" changeset). Then, a changeset based +** on S0 is received from another site (the "remote" changeset) and +** applied to the database. The database is then in state +** (S1+"remote"), where the exact state depends on any conflict +** resolution decisions (OMIT or REPLACE) made while applying "remote". +** Rebasing a changeset is to update it to take those conflict +** resolution decisions into account, so that the same conflicts +** do not have to be resolved elsewhere in the network. +** +** For example, if both the local and remote changesets contain an +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": +** +** local: INSERT INTO t1 VALUES(1, 'v1'); +** remote: INSERT INTO t1 VALUES(1, 'v2'); +** +** and the conflict resolution is REPLACE, then the INSERT change is +** removed from the local changeset (it was overridden). Or, if the +** conflict resolution was "OMIT", then the local changeset is modified +** to instead contain: +** +** UPDATE t1 SET b = 'v2' WHERE a=1; +** +** Changes within the local changeset are rebased as follows: +** +**
    +**
    Local INSERT
    +** This may only conflict with a remote INSERT. If the conflict +** resolution was OMIT, then add an UPDATE change to the rebased +** changeset. Or, if the conflict resolution was REPLACE, add +** nothing to the rebased changeset. +** +**
    Local DELETE
    +** This may conflict with a remote UPDATE or DELETE. In both cases the +** only possible resolution is OMIT. If the remote operation was a +** DELETE, then add no change to the rebased changeset. If the remote +** operation was an UPDATE, then the old.* fields of change are updated +** to reflect the new.* values in the UPDATE. +** +**
    Local UPDATE
    +** This may conflict with a remote UPDATE or DELETE. If it conflicts +** with a DELETE, and the conflict resolution was OMIT, then the update +** is changed into an INSERT. Any undefined values in the new.* record +** from the update change are filled in using the old.* values from +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, +** the UPDATE change is simply omitted from the rebased changeset. +** +** If conflict is with a remote UPDATE and the resolution is OMIT, then +** the old.* values are rebased using the new.* values in the remote +** change. Or, if the resolution is REPLACE, then the change is copied +** into the rebased changeset with updates to columns also updated by +** the conflicting remote UPDATE removed. If this means no columns would +** be updated, the change is omitted. +**
    +** +** A local change may be rebased against multiple remote changes +** simultaneously. If a single key is modified by multiple remote +** changesets, they are combined as follows before the local changeset +** is rebased: +** +**
      +**
    • If there has been one or more REPLACE resolutions on a +** key, it is rebased according to a REPLACE. +** +**
    • If there have been no REPLACE resolutions on a key, then +** the local changeset is rebased according to the most recent +** of the OMIT resolutions. +**
    +** +** Note that conflict resolutions from multiple remote changesets are +** combined on a per-field basis, not per-row. This means that in the +** case of multiple remote UPDATE operations, some fields of a single +** local change may be rebased for REPLACE while others are rebased for +** OMIT. +** +** In order to rebase a local changeset, the remote changeset must first +** be applied to the local database using sqlite3changeset_apply_v2() and +** the buffer of rebase information captured. Then: +** +**
      +**
    1. An sqlite3_rebaser object is created by calling +** sqlite3rebaser_create(). +**
    2. The new object is configured with the rebase buffer obtained from +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). +** If the local changeset is to be rebased against multiple remote +** changesets, then sqlite3rebaser_configure() should be called +** multiple times, in the same order that the multiple +** sqlite3changeset_apply_v2() calls were made. +**
    3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). +**
    4. The sqlite3_rebaser object is deleted by calling +** sqlite3rebaser_delete(). +**
    +*/ +typedef struct sqlite3_rebaser sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object. +** EXPERIMENTAL +** +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to +** point to the new object and return SQLITE_OK. Otherwise, if an error +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) +** to NULL. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object. +** EXPERIMENTAL +** +** Configure the changeset rebaser object to rebase changesets according +** to the conflict resolutions described by buffer pRebase (size nRebase +** bytes), which must have been obtained from a previous call to +** sqlite3changeset_apply_v2(). +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, const void *pRebase +); + +/* +** CAPI3REF: Rebase a changeset +** EXPERIMENTAL +** +** Argument pIn must point to a buffer containing a changeset nIn bytes +** in size. This function allocates and populates a buffer with a copy +** of the changeset rebased rebased according to the configuration of the +** rebaser object passed as the first argument. If successful, (*ppOut) +** is set to point to the new buffer containing the rebased changset and +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the +** responsibility of the caller to eventually free the new buffer using +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) +** are set to zero and an SQLite error code returned. +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object. +** EXPERIMENTAL +** +** Delete the changeset rebaser object and all associated resources. There +** should be one call to this function for each successful invocation +** of sqlite3rebaser_create(). +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); + /* ** CAPI3REF: Streaming Versions of API functions. ** @@ -10001,6 +10683,7 @@ SQLITE_API int sqlite3changeset_apply( ** ** **
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_strm[sqlite3changeset_apply] +**
    sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] **
    sqlite3changeset_concat_strm[sqlite3changeset_concat] **
    sqlite3changeset_invert_strm[sqlite3changeset_invert] **
    sqlite3changeset_start_strm[sqlite3changeset_start] @@ -10096,6 +10779,23 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, @@ -10133,6 +10833,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); /* @@ -10729,4 +11436,100 @@ struct fts5_api { #else // USE_LIBSQLITE3 // If users really want to link against the system sqlite3 we // need to make this file a noop. - #endif \ No newline at end of file + #endif +/* +** 2014-09-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the application interface definitions for the +** user-authentication extension feature. +** +** To compile with the user-authentication feature, append this file to +** end of an SQLite amalgamation header file ("sqlite3.h"), then add +** the SQLITE_USER_AUTHENTICATION compile-time option. See the +** user-auth.txt file in the same source directory as this file for +** additional information. +*/ +#ifdef SQLITE_USER_AUTHENTICATION + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** If a database contains the SQLITE_USER table, then the +** sqlite3_user_authenticate() interface must be invoked with an +** appropriate username and password prior to enable read and write +** access to the database. +** +** Return SQLITE_OK on success or SQLITE_ERROR if the username/password +** combination is incorrect or unknown. +** +** If the SQLITE_USER table is not present in the database file, then +** this interface is a harmless no-op returnning SQLITE_OK. +*/ +int sqlite3_user_authenticate( + sqlite3 *db, /* The database connection */ + const char *zUsername, /* Username */ + const char *aPW, /* Password or credentials */ + int nPW /* Number of bytes in aPW[] */ +); + +/* +** The sqlite3_user_add() interface can be used (by an admin user only) +** to create a new user. When called on a no-authentication-required +** database, this routine converts the database into an authentication- +** required database, automatically makes the added user an +** administrator, and logs in the current connection as that user. +** The sqlite3_user_add() interface only works for the "main" database, not +** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a +** non-admin user results in an error. +*/ +int sqlite3_user_add( + sqlite3 *db, /* Database connection */ + const char *zUsername, /* Username to be added */ + const char *aPW, /* Password or credentials */ + int nPW, /* Number of bytes in aPW[] */ + int isAdmin /* True to give new user admin privilege */ +); + +/* +** The sqlite3_user_change() interface can be used to change a users +** login credentials or admin privilege. Any user can change their own +** login credentials. Only an admin user can change another users login +** credentials or admin privilege setting. No user may change their own +** admin privilege setting. +*/ +int sqlite3_user_change( + sqlite3 *db, /* Database connection */ + const char *zUsername, /* Username to change */ + const char *aPW, /* New password or credentials */ + int nPW, /* Number of bytes in aPW[] */ + int isAdmin /* Modified admin privilege for the user */ +); + +/* +** The sqlite3_user_delete() interface can be used (by an admin user only) +** to delete a user. The currently logged-in user cannot be deleted, +** which guarantees that there is always an admin user and hence that +** the database cannot be converted into a no-authentication-required +** database. +*/ +int sqlite3_user_delete( + sqlite3 *db, /* Database connection */ + const char *zUsername /* Username to remove */ +); + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* SQLITE_USER_AUTHENTICATION */ diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3.go index 739f91d..d8fe4b0 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3.go @@ -1,17 +1,28 @@ // Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. +// +build cgo + package sqlite3 /* #cgo CFLAGS: -std=gnu99 -#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE=1 -#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61 +#cgo CFLAGS: -DSQLITE_ENABLE_RTREE +#cgo CFLAGS: -DSQLITE_THREADSAFE=1 +#cgo CFLAGS: -DHAVE_USLEEP=1 +#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 +#cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS +#cgo CFLAGS: -DSQLITE_ENABLE_FTS4_UNICODE61 #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15 +#cgo CFLAGS: -DSQLITE_OMIT_DEPRECATED #cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC +#cgo CFLAGS: -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 +#cgo CFLAGS: -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT #cgo CFLAGS: -Wno-deprecated-declarations +#cgo linux,!android CFLAGS: -DHAVE_PREAD64=1 -DHAVE_PWRITE64=1 #ifndef USE_LIBSQLITE3 #include #else @@ -170,6 +181,12 @@ var SQLiteTimestampFormats = []string{ "2006-01-02", } +const ( + columnDate string = "date" + columnDatetime string = "datetime" + columnTimestamp string = "timestamp" +) + func init() { sql.Register("sqlite3", &SQLiteDriver{}) } @@ -389,7 +406,7 @@ func (c *SQLiteConn) RegisterCommitHook(callback func() int) { if callback == nil { C.sqlite3_commit_hook(c.db, nil, nil) } else { - C.sqlite3_commit_hook(c.db, (*[0]byte)(unsafe.Pointer(C.commitHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) + C.sqlite3_commit_hook(c.db, (*[0]byte)(C.commitHookTrampoline), unsafe.Pointer(newHandle(c, callback))) } } @@ -402,7 +419,7 @@ func (c *SQLiteConn) RegisterRollbackHook(callback func()) { if callback == nil { C.sqlite3_rollback_hook(c.db, nil, nil) } else { - C.sqlite3_rollback_hook(c.db, (*[0]byte)(unsafe.Pointer(C.rollbackHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) + C.sqlite3_rollback_hook(c.db, (*[0]byte)(C.rollbackHookTrampoline), unsafe.Pointer(newHandle(c, callback))) } } @@ -419,7 +436,7 @@ func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64 if callback == nil { C.sqlite3_update_hook(c.db, nil, nil) } else { - C.sqlite3_update_hook(c.db, (*[0]byte)(unsafe.Pointer(C.updateHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) + C.sqlite3_update_hook(c.db, (*[0]byte)(C.updateHookTrampoline), unsafe.Pointer(newHandle(c, callback))) } } @@ -501,7 +518,7 @@ func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) erro } func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int { - return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(unsafe.Pointer(xFunc)), (*[0]byte)(unsafe.Pointer(xStep)), (*[0]byte)(unsafe.Pointer(xFinal))) + return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(xFunc), (*[0]byte)(xStep), (*[0]byte)(xFinal)) } // RegisterAggregator makes a Go type available as a SQLite aggregation function. @@ -763,33 +780,140 @@ func errorString(err Error) string { } // Open database and return a new connection. +// +// A pragma can take either zero or one argument. +// The argument is may be either in parentheses or it may be separated from +// the pragma name by an equal sign. The two syntaxes yield identical results. +// In many pragmas, the argument is a boolean. The boolean can be one of: +// 1 yes true on +// 0 no false off +// // You can specify a DSN string using a URI as the filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: +// +// mode +// Access mode of the database. +// https://www.sqlite.org/c3ref/open.html +// Values: +// - ro +// - rw +// - rwc +// - memory +// +// shared +// SQLite Shared-Cache Mode +// https://www.sqlite.org/sharedcache.html +// Values: +// - shared +// - private +// +// immutable=Boolean +// The immutable parameter is a boolean query parameter that indicates +// that the database file is stored on read-only media. When immutable is set, +// SQLite assumes that the database file cannot be changed, +// even by a process with higher privilege, +// and so the database is opened read-only and all locking and change detection is disabled. +// Caution: Setting the immutable property on a database file that +// does in fact change can result in incorrect query results and/or SQLITE_CORRUPT errors. +// // go-sqlite3 adds the following query parameters to those used by SQLite: // _loc=XXX // Specify location of time format. It's possible to specify "auto". -// _busy_timeout=XXX -// Specify value for sqlite3_busy_timeout. +// +// _mutex=XXX +// Specify mutex mode. XXX can be "no", "full". +// // _txlock=XXX // Specify locking behavior for transactions. XXX can be "immediate", // "deferred", "exclusive". -// _foreign_keys=X -// Enable or disable enforcement of foreign keys. X can be 1 or 0. -// _recursive_triggers=X -// Enable or disable recursive triggers. X can be 1 or 0. +// +// _auto_vacuum=X | _vacuum=X +// 0 | none - Auto Vacuum disabled +// 1 | full - Auto Vacuum FULL +// 2 | incremental - Auto Vacuum Incremental +// +// _busy_timeout=XXX"| _timeout=XXX +// Specify value for sqlite3_busy_timeout. +// +// _case_sensitive_like=Boolean | _cslike=Boolean +// https://www.sqlite.org/pragma.html#pragma_case_sensitive_like +// Default or disabled the LIKE operation is case-insensitive. +// When enabling this options behaviour of LIKE will become case-sensitive. +// +// _defer_foreign_keys=Boolean | _defer_fk=Boolean +// Defer Foreign Keys until outermost transaction is committed. +// +// _foreign_keys=Boolean | _fk=Boolean +// Enable or disable enforcement of foreign keys. +// +// _ignore_check_constraints=Boolean +// This pragma enables or disables the enforcement of CHECK constraints. +// The default setting is off, meaning that CHECK constraints are enforced by default. +// +// _journal_mode=MODE | _journal=MODE +// Set journal mode for the databases associated with the current connection. +// https://www.sqlite.org/pragma.html#pragma_journal_mode +// +// _locking_mode=X | _locking=X +// Sets the database connection locking-mode. +// The locking-mode is either NORMAL or EXCLUSIVE. +// https://www.sqlite.org/pragma.html#pragma_locking_mode +// +// _query_only=Boolean +// The query_only pragma prevents all changes to database files when enabled. +// +// _recursive_triggers=Boolean | _rt=Boolean +// Enable or disable recursive triggers. +// +// _secure_delete=Boolean|FAST +// When secure_delete is on, SQLite overwrites deleted content with zeros. +// https://www.sqlite.org/pragma.html#pragma_secure_delete +// +// _synchronous=X | _sync=X +// Change the setting of the "synchronous" flag. +// https://www.sqlite.org/pragma.html#pragma_synchronous +// +// _writable_schema=Boolean +// When this pragma is on, the SQLITE_MASTER tables in which database +// can be changed using ordinary UPDATE, INSERT, and DELETE statements. +// Warning: misuse of this pragma can easily result in a corrupt database file. +// +// func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { if C.sqlite3_threadsafe() == 0 { return nil, errors.New("sqlite library was not compiled for thread-safe operation") } + var pkey string + + // Options var loc *time.Location + authCreate := false + authUser := "" + authPass := "" + authCrypt := "" + authSalt := "" + mutex := C.int(C.SQLITE_OPEN_FULLMUTEX) txlock := "BEGIN" + + // PRAGMA's + autoVacuum := -1 busyTimeout := 5000 + caseSensitiveLike := -1 + deferForeignKeys := -1 foreignKeys := -1 + ignoreCheckConstraints := -1 + journalMode := "DELETE" + lockingMode := "NORMAL" + queryOnly := -1 recursiveTriggers := -1 + secureDelete := "DEFAULT" + synchronousMode := "NORMAL" + writableSchema := -1 + pos := strings.IndexRune(dsn, '?') if pos >= 1 { params, err := url.ParseQuery(dsn[pos+1:]) @@ -797,11 +921,29 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { return nil, err } + // Authentication + if _, ok := params["_auth"]; ok { + authCreate = true + } + if val := params.Get("_auth_user"); val != "" { + authUser = val + } + if val := params.Get("_auth_pass"); val != "" { + authPass = val + } + if val := params.Get("_auth_crypt"); val != "" { + authCrypt = val + } + if val := params.Get("_auth_salt"); val != "" { + authSalt = val + } + // _loc if val := params.Get("_loc"); val != "" { - if val == "auto" { + switch strings.ToLower(val) { + case "auto": loc = time.Local - } else { + default: loc, err = time.LoadLocation(val) if err != nil { return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err) @@ -809,18 +951,21 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { } } - // _busy_timeout - if val := params.Get("_busy_timeout"); val != "" { - iv, err := strconv.ParseInt(val, 10, 64) - if err != nil { - return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) + // _mutex + if val := params.Get("_mutex"); val != "" { + switch strings.ToLower(val) { + case "no": + mutex = C.SQLITE_OPEN_NOMUTEX + case "full": + mutex = C.SQLITE_OPEN_FULLMUTEX + default: + return nil, fmt.Errorf("Invalid _mutex: %v", val) } - busyTimeout = int(iv) } // _txlock if val := params.Get("_txlock"); val != "" { - switch val { + switch strings.ToLower(val) { case "immediate": txlock = "BEGIN IMMEDIATE" case "exclusive": @@ -832,27 +977,262 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { } } - // _foreign_keys - if val := params.Get("_foreign_keys"); val != "" { - switch val { - case "1": - foreignKeys = 1 - case "0": - foreignKeys = 0 + // Auto Vacuum (_vacuum) + // + // https://www.sqlite.org/pragma.html#pragma_auto_vacuum + // + pkey = "" // Reset pkey + if _, ok := params["_auto_vacuum"]; ok { + pkey = "_auto_vacuum" + } + if _, ok := params["_vacuum"]; ok { + pkey = "_vacuum" + } + if val := params.Get(pkey); val != "" { + switch strings.ToLower(val) { + case "0", "none": + autoVacuum = 0 + case "1", "full": + autoVacuum = 1 + case "2", "incremental": + autoVacuum = 2 default: - return nil, fmt.Errorf("Invalid _foreign_keys: %v", val) + return nil, fmt.Errorf("Invalid _auto_vacuum: %v, expecting value of '0 NONE 1 FULL 2 INCREMENTAL'", val) } } - // _recursive_triggers - if val := params.Get("_recursive_triggers"); val != "" { - switch val { - case "1": - recursiveTriggers = 1 - case "0": - recursiveTriggers = 0 + // Busy Timeout (_busy_timeout) + // + // https://www.sqlite.org/pragma.html#pragma_busy_timeout + // + pkey = "" // Reset pkey + if _, ok := params["_busy_timeout"]; ok { + pkey = "_busy_timeout" + } + if _, ok := params["_timeout"]; ok { + pkey = "_timeout" + } + if val := params.Get(pkey); val != "" { + iv, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) + } + busyTimeout = int(iv) + } + + // Case Sensitive Like (_cslike) + // + // https://www.sqlite.org/pragma.html#pragma_case_sensitive_like + // + pkey = "" // Reset pkey + if _, ok := params["_case_sensitive_like"]; ok { + pkey = "_case_sensitive_like" + } + if _, ok := params["_cslike"]; ok { + pkey = "_cslike" + } + if val := params.Get(pkey); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + caseSensitiveLike = 0 + case "1", "yes", "true", "on": + caseSensitiveLike = 1 default: - return nil, fmt.Errorf("Invalid _recursive_triggers: %v", val) + return nil, fmt.Errorf("Invalid _case_sensitive_like: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Defer Foreign Keys (_defer_foreign_keys | _defer_fk) + // + // https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys + // + pkey = "" // Reset pkey + if _, ok := params["_defer_foreign_keys"]; ok { + pkey = "_defer_foreign_keys" + } + if _, ok := params["_defer_fk"]; ok { + pkey = "_defer_fk" + } + if val := params.Get(pkey); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + deferForeignKeys = 0 + case "1", "yes", "true", "on": + deferForeignKeys = 1 + default: + return nil, fmt.Errorf("Invalid _defer_foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Foreign Keys (_foreign_keys | _fk) + // + // https://www.sqlite.org/pragma.html#pragma_foreign_keys + // + pkey = "" // Reset pkey + if _, ok := params["_foreign_keys"]; ok { + pkey = "_foreign_keys" + } + if _, ok := params["_fk"]; ok { + pkey = "_fk" + } + if val := params.Get(pkey); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + foreignKeys = 0 + case "1", "yes", "true", "on": + foreignKeys = 1 + default: + return nil, fmt.Errorf("Invalid _foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Ignore CHECK Constrains (_ignore_check_constraints) + // + // https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints + // + if val := params.Get("_ignore_check_constraints"); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + ignoreCheckConstraints = 0 + case "1", "yes", "true", "on": + ignoreCheckConstraints = 1 + default: + return nil, fmt.Errorf("Invalid _ignore_check_constraints: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Journal Mode (_journal_mode | _journal) + // + // https://www.sqlite.org/pragma.html#pragma_journal_mode + // + pkey = "" // Reset pkey + if _, ok := params["_journal_mode"]; ok { + pkey = "_journal_mode" + } + if _, ok := params["_journal"]; ok { + pkey = "_journal" + } + if val := params.Get(pkey); val != "" { + switch strings.ToUpper(val) { + case "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "OFF": + journalMode = strings.ToUpper(val) + case "WAL": + journalMode = strings.ToUpper(val) + + // For WAL Mode set Synchronous Mode to 'NORMAL' + // See https://www.sqlite.org/pragma.html#pragma_synchronous + synchronousMode = "NORMAL" + default: + return nil, fmt.Errorf("Invalid _journal: %v, expecting value of 'DELETE TRUNCATE PERSIST MEMORY WAL OFF'", val) + } + } + + // Locking Mode (_locking) + // + // https://www.sqlite.org/pragma.html#pragma_locking_mode + // + pkey = "" // Reset pkey + if _, ok := params["_locking_mode"]; ok { + pkey = "_locking_mode" + } + if _, ok := params["_locking"]; ok { + pkey = "_locking" + } + if val := params.Get("_locking"); val != "" { + switch strings.ToUpper(val) { + case "NORMAL", "EXCLUSIVE": + lockingMode = strings.ToUpper(val) + default: + return nil, fmt.Errorf("Invalid _locking_mode: %v, expecting value of 'NORMAL EXCLUSIVE", val) + } + } + + // Query Only (_query_only) + // + // https://www.sqlite.org/pragma.html#pragma_query_only + // + if val := params.Get("_query_only"); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + queryOnly = 0 + case "1", "yes", "true", "on": + queryOnly = 1 + default: + return nil, fmt.Errorf("Invalid _query_only: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Recursive Triggers (_recursive_triggers) + // + // https://www.sqlite.org/pragma.html#pragma_recursive_triggers + // + pkey = "" // Reset pkey + if _, ok := params["_recursive_triggers"]; ok { + pkey = "_recursive_triggers" + } + if _, ok := params["_rt"]; ok { + pkey = "_rt" + } + if val := params.Get(pkey); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + recursiveTriggers = 0 + case "1", "yes", "true", "on": + recursiveTriggers = 1 + default: + return nil, fmt.Errorf("Invalid _recursive_triggers: %v, expecting boolean value of '0 1 false true no yes off on'", val) + } + } + + // Secure Delete (_secure_delete) + // + // https://www.sqlite.org/pragma.html#pragma_secure_delete + // + if val := params.Get("_secure_delete"); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + secureDelete = "OFF" + case "1", "yes", "true", "on": + secureDelete = "ON" + case "fast": + secureDelete = "FAST" + default: + return nil, fmt.Errorf("Invalid _secure_delete: %v, expecting boolean value of '0 1 false true no yes off on fast'", val) + } + } + + // Synchronous Mode (_synchronous | _sync) + // + // https://www.sqlite.org/pragma.html#pragma_synchronous + // + pkey = "" // Reset pkey + if _, ok := params["_synchronous"]; ok { + pkey = "_synchronous" + } + if _, ok := params["_sync"]; ok { + pkey = "_sync" + } + if val := params.Get(pkey); val != "" { + switch strings.ToUpper(val) { + case "0", "OFF", "1", "NORMAL", "2", "FULL", "3", "EXTRA": + synchronousMode = strings.ToUpper(val) + default: + return nil, fmt.Errorf("Invalid _synchronous: %v, expecting value of '0 OFF 1 NORMAL 2 FULL 3 EXTRA'", val) + } + } + + // Writable Schema (_writeable_schema) + // + // https://www.sqlite.org/pragma.html#pragma_writeable_schema + // + if val := params.Get("_writable_schema"); val != "" { + switch strings.ToLower(val) { + case "0", "no", "false", "off": + writableSchema = 0 + case "1", "yes", "true", "on": + writableSchema = 1 + default: + return nil, fmt.Errorf("Invalid _writable_schema: %v, expecting boolean value of '0 1 false true no yes off on'", val) } } @@ -865,9 +1245,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { name := C.CString(dsn) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, - C.SQLITE_OPEN_FULLMUTEX| - C.SQLITE_OPEN_READWRITE| - C.SQLITE_OPEN_CREATE, + mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, Error{Code: ErrNo(rv)} @@ -891,30 +1269,268 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { } return nil } - if foreignKeys == 0 { - if err := exec("PRAGMA foreign_keys = OFF;"); err != nil { - C.sqlite3_close_v2(db) - return nil, err - } - } else if foreignKeys == 1 { - if err := exec("PRAGMA foreign_keys = ON;"); err != nil { - C.sqlite3_close_v2(db) - return nil, err + + // USER AUTHENTICATION + // + // User Authentication is always performed even when + // sqlite_userauth is not compiled in, because without user authentication + // the authentication is a no-op. + // + // Workflow + // - Authenticate + // ON::SUCCESS => Continue + // ON::SQLITE_AUTH => Return error and exit Open(...) + // + // - Activate User Authentication + // Check if the user wants to activate User Authentication. + // If so then first create a temporary AuthConn to the database + // This is possible because we are already succesfully authenticated. + // + // - Check if `sqlite_user`` table exists + // YES => Add the provided user from DSN as Admin User and + // activate user authentication. + // NO => Continue + // + + // Create connection to SQLite + conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} + + // Password Cipher has to be registerd before authentication + if len(authCrypt) > 0 { + switch strings.ToUpper(authCrypt) { + case "SHA1": + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil { + return nil, fmt.Errorf("CryptEncoderSHA1: %s", err) + } + case "SSHA1": + if len(authSalt) == 0 { + return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt") + } + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil { + return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err) + } + case "SHA256": + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil { + return nil, fmt.Errorf("CryptEncoderSHA256: %s", err) + } + case "SSHA256": + if len(authSalt) == 0 { + return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt") + } + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil { + return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err) + } + case "SHA384": + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil { + return nil, fmt.Errorf("CryptEncoderSHA384: %s", err) + } + case "SSHA384": + if len(authSalt) == 0 { + return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt") + } + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil { + return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err) + } + case "SHA512": + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil { + return nil, fmt.Errorf("CryptEncoderSHA512: %s", err) + } + case "SSHA512": + if len(authSalt) == 0 { + return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt") + } + if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil { + return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err) + } } } - if recursiveTriggers == 0 { - if err := exec("PRAGMA recursive_triggers = OFF;"); err != nil { - C.sqlite3_close_v2(db) - return nil, err - } - } else if recursiveTriggers == 1 { - if err := exec("PRAGMA recursive_triggers = ON;"); err != nil { + + // Preform Authentication + if err := conn.Authenticate(authUser, authPass); err != nil { + return nil, err + } + + // Register: authenticate + // Authenticate will perform an authentication of the provided username + // and password against the database. + // + // If a database contains the SQLITE_USER table, then the + // call to Authenticate must be invoked with an + // appropriate username and password prior to enable read and write + //access to the database. + // + // Return SQLITE_OK on success or SQLITE_ERROR if the username/password + // combination is incorrect or unknown. + // + // If the SQLITE_USER table is not present in the database file, then + // this interface is a harmless no-op returnning SQLITE_OK. + if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil { + return nil, err + } + // + // Register: auth_user_add + // auth_user_add can be used (by an admin user only) + // to create a new user. When called on a no-authentication-required + // database, this routine converts the database into an authentication- + // required database, automatically makes the added user an + // administrator, and logs in the current connection as that user. + // The AuthUserAdd only works for the "main" database, not + // for any ATTACH-ed databases. Any call to AuthUserAdd by a + // non-admin user results in an error. + if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil { + return nil, err + } + // + // Register: auth_user_change + // auth_user_change can be used to change a users + // login credentials or admin privilege. Any user can change their own + // login credentials. Only an admin user can change another users login + // credentials or admin privilege setting. No user may change their own + // admin privilege setting. + if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil { + return nil, err + } + // + // Register: auth_user_delete + // auth_user_delete can be used (by an admin user only) + // to delete a user. The currently logged-in user cannot be deleted, + // which guarantees that there is always an admin user and hence that + // the database cannot be converted into a no-authentication-required + // database. + if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil { + return nil, err + } + + // Register: auth_enabled + // auth_enabled can be used to check if user authentication is enabled + if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil { + return nil, err + } + + // Auto Vacuum + // Moved auto_vacuum command, the user preference for auto_vacuum needs to be implemented directly after + // the authentication and before the sqlite_user table gets created if the user + // decides to activate User Authentication because + // auto_vacuum needs to be set before any tables are created + // and activating user authentication creates the internal table `sqlite_user`. + if autoVacuum > -1 { + if err := exec(fmt.Sprintf("PRAGMA auto_vacuum = %d;", autoVacuum)); err != nil { C.sqlite3_close_v2(db) return nil, err } } - conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} + // Check if user wants to activate User Authentication + if authCreate { + // Before going any further, we need to check that the user + // has provided an username and password within the DSN. + // We are not allowed to continue. + if len(authUser) < 0 { + return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'") + } + if len(authPass) < 0 { + return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'") + } + + // Check if User Authentication is Enabled + authExists := conn.AuthEnabled() + if !authExists { + if err := conn.AuthUserAdd(authUser, authPass, true); err != nil { + return nil, err + } + } + } + + // Case Sensitive LIKE + if caseSensitiveLike > -1 { + if err := exec(fmt.Sprintf("PRAGMA case_sensitive_like = %d;", caseSensitiveLike)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Defer Foreign Keys + if deferForeignKeys > -1 { + if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Forgein Keys + if foreignKeys > -1 { + if err := exec(fmt.Sprintf("PRAGMA foreign_keys = %d;", foreignKeys)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Ignore CHECK Constraints + if ignoreCheckConstraints > -1 { + if err := exec(fmt.Sprintf("PRAGMA ignore_check_constraints = %d;", ignoreCheckConstraints)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Journal Mode + // Because default Journal Mode is DELETE this PRAGMA can always be executed. + if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + + // Locking Mode + // Because the default is NORMAL and this is not changed in this package + // by using the compile time SQLITE_DEFAULT_LOCKING_MODE this PRAGMA can always be executed + if err := exec(fmt.Sprintf("PRAGMA locking_mode = %s;", lockingMode)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + + // Query Only + if queryOnly > -1 { + if err := exec(fmt.Sprintf("PRAGMA query_only = %d;", queryOnly)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Recursive Triggers + if recursiveTriggers > -1 { + if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Secure Delete + // + // Because this package can set the compile time flag SQLITE_SECURE_DELETE with a build tag + // the default value for secureDelete var is 'DEFAULT' this way + // you can compile with secure_delete 'ON' and disable it for a specific database connection. + if secureDelete != "DEFAULT" { + if err := exec(fmt.Sprintf("PRAGMA secure_delete = %s;", secureDelete)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } + + // Synchronous Mode + // + // Because default is NORMAL this statement is always executed + if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + + // Writable Schema + if writableSchema > -1 { + if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } if len(d.Extensions) > 0 { if err := conn.loadExtensions(d.Extensions); err != nil { @@ -996,6 +1612,17 @@ const ( SQLITE_LIMIT_WORKER_THREADS = C.SQLITE_LIMIT_WORKER_THREADS ) +// GetFilename returns the absolute path to the file containing +// the requested schema. When passed an empty string, it will +// instead use the database's default schema: "main". +// See: sqlite3_db_filename, https://www.sqlite.org/c3ref/db_filename.html +func (c *SQLiteConn) GetFilename(schemaName string) string { + if schemaName == "" { + schemaName = "main" + } + return C.GoString(C.sqlite3_db_filename(c.db, C.CString(schemaName))) +} + // GetLimit returns the current value of a run-time limit. // See: sqlite3_limit, http://www.sqlite.org/c3ref/limit.html func (c *SQLiteConn) GetLimit(id int) int { @@ -1070,7 +1697,7 @@ func (s *SQLiteStmt) bind(args []namedValue) error { case int64: rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v)) case bool: - if bool(v) { + if v { rv = C.sqlite3_bind_int(s.s, n, 1) } else { rv = C.sqlite3_bind_int(s.s, n, 0) @@ -1078,11 +1705,15 @@ func (s *SQLiteStmt) bind(args []namedValue) error { case float64: rv = C.sqlite3_bind_double(s.s, n, C.double(v)) case []byte: - ln := len(v) - if ln == 0 { - v = placeHolder + if v == nil { + rv = C.sqlite3_bind_null(s.s, n) + } else { + ln := len(v) + if ln == 0 { + v = placeHolder + } + rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln)) } - rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln)) case time.Time: b := []byte(v.Format(SQLiteTimestampFormats[0])) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) @@ -1121,18 +1752,20 @@ func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows, done: make(chan struct{}), } - go func(db *C.sqlite3) { - select { - case <-ctx.Done(): + if ctxdone := ctx.Done(); ctxdone != nil { + go func(db *C.sqlite3) { select { + case <-ctxdone: + select { + case <-rows.done: + default: + C.sqlite3_interrupt(db) + rows.Close() + } case <-rows.done: - default: - C.sqlite3_interrupt(db) - rows.Close() } - case <-rows.done: - } - }(s.c.db) + }(s.c.db) + } return rows, nil } @@ -1166,19 +1799,21 @@ func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result return nil, err } - done := make(chan struct{}) - defer close(done) - go func(db *C.sqlite3) { - select { - case <-done: - case <-ctx.Done(): + if ctxdone := ctx.Done(); ctxdone != nil { + done := make(chan struct{}) + defer close(done) + go func(db *C.sqlite3) { select { case <-done: - default: - C.sqlite3_interrupt(db) + case <-ctxdone: + select { + case <-done: + default: + C.sqlite3_interrupt(db) + } } - } - }(s.c.db) + }(s.c.db) + } var rowid, changes C.longlong rv := C._sqlite3_step(s.s, &rowid, &changes) @@ -1272,7 +1907,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { - case "timestamp", "datetime", "date": + case columnTimestamp, columnDatetime, columnDate: var t time.Time // Assume a millisecond unix timestamp if it's 13 digits -- too // large to be a reasonable timestamp in seconds. @@ -1302,11 +1937,9 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { } n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) switch dest[i].(type) { - case sql.RawBytes: - dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) - copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) + copy(slice[:], (*[1 << 30]byte)(p)[0:n]) dest[i] = slice } case C.SQLITE_NULL: @@ -1319,7 +1952,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n)) switch rc.decltype[i] { - case "timestamp", "datetime", "date": + case columnTimestamp, columnDatetime, columnDate: var t time.Time s = strings.TrimSuffix(s, "Z") for _, format := range SQLiteTimestampFormats { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go new file mode 100644 index 0000000..3774a97 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go @@ -0,0 +1,120 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package sqlite3 + +import ( + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" +) + +// This file provides several different implementations for the +// default embedded sqlite_crypt function. +// This function is uses a ceasar-cypher by default +// and is used within the UserAuthentication module to encode +// the password. +// +// The provided functions can be used as an overload to the sqlite_crypt +// function through the use of the RegisterFunc on the connection. +// +// Because the functions can serv a purpose to an end-user +// without using the UserAuthentication module +// the functions are default compiled in. +// +// From SQLITE3 - user-auth.txt +// The sqlite_user.pw field is encoded by a built-in SQL function +// "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument +// is the plaintext password supplied to the sqlite3_user_authenticate() +// interface. The second argument is the sqlite_user.pw value and is supplied +// so that the function can extract the "salt" used by the password encoder. +// The result of sqlite_crypt(X,Y) is another blob which is the value that +// ends up being stored in sqlite_user.pw. To verify credentials X supplied +// by the sqlite3_user_authenticate() routine, SQLite runs: +// +// sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw) +// +// To compute an appropriate sqlite_user.pw value from a new or modified +// password X, sqlite_crypt(X,NULL) is run. A new random salt is selected +// when the second argument is NULL. +// +// The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher +// which prevents passwords from being revealed by searching the raw database +// for ASCII text, but is otherwise trivally broken. For better password +// security, the database should be encrypted using the SQLite Encryption +// Extension or similar technology. Or, the application can use the +// sqlite3_create_function() interface to provide an alternative +// implementation of sqlite_crypt() that computes a stronger password hash, +// perhaps using a cryptographic hash function like SHA1. + +// CryptEncoderSHA1 encodes a password with SHA1 +func CryptEncoderSHA1(pass []byte, hash interface{}) []byte { + h := sha1.Sum(pass) + return h[:] +} + +// CryptEncoderSSHA1 encodes a password with SHA1 with the +// configured salt. +func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte { + return func(pass []byte, hash interface{}) []byte { + s := []byte(salt) + p := append(pass, s...) + h := sha1.Sum(p) + return h[:] + } +} + +// CryptEncoderSHA256 encodes a password with SHA256 +func CryptEncoderSHA256(pass []byte, hash interface{}) []byte { + h := sha256.Sum256(pass) + return h[:] +} + +// CryptEncoderSSHA256 encodes a password with SHA256 +// with the configured salt +func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte { + return func(pass []byte, hash interface{}) []byte { + s := []byte(salt) + p := append(pass, s...) + h := sha256.Sum256(p) + return h[:] + } +} + +// CryptEncoderSHA384 encodes a password with SHA256 +func CryptEncoderSHA384(pass []byte, hash interface{}) []byte { + h := sha512.Sum384(pass) + return h[:] +} + +// CryptEncoderSSHA384 encodes a password with SHA256 +// with the configured salt +func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte { + return func(pass []byte, hash interface{}) []byte { + s := []byte(salt) + p := append(pass, s...) + h := sha512.Sum384(p) + return h[:] + } +} + +// CryptEncoderSHA512 encodes a password with SHA256 +func CryptEncoderSHA512(pass []byte, hash interface{}) []byte { + h := sha512.Sum512(pass) + return h[:] +} + +// CryptEncoderSSHA512 encodes a password with SHA256 +// with the configured salt +func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte { + return func(pass []byte, hash interface{}) []byte { + s := []byte(salt) + p := append(pass, s...) + h := sha512.Sum512(p) + return h[:] + } +} + +// EOF diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go new file mode 100644 index 0000000..0329ca8 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go @@ -0,0 +1,57 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package sqlite3 + +import ( + "fmt" + "strings" + "testing" +) + +// TestCryptEncoders to increase coverage +func TestCryptEncoders(t *testing.T) { + tests := []struct { + enc string + salt string + expected string + }{ + {"sha1", "", "d033e22ae348aeb5660fc2140aec35850c4da997"}, + {"sha256", "", "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"}, + {"sha384", "", "9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782"}, + {"sha512", "", "c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec"}, + {"ssha1", "salt", "9bc7aa55f08fdad935c3f8362d3f48bcf70eb280"}, + {"ssha256", "salt", "f9a81477552594c79f2abc3fc099daa896a6e3a3590a55ffa392b6000412e80b"}, + {"ssha384", "salt", "9ed776b477fcfc1b5e584989e8d770f5e17d98a7643546a63c2b07d4ab00f1348f6b8e73103d3a23554f727136e8c215"}, + {"ssha512", "salt", "3c4a79782143337be4492be072abcfe979dd703c00541a8c39a0f3df4bab2029c050cf46fddc47090b5b04ac537b3e78189e3de16e601e859f95c51ac9f6dafb"}, + } + + for _, e := range tests { + var fn func(pass []byte, hash interface{}) []byte + switch e.enc { + case "sha1": + fn = CryptEncoderSHA1 + case "ssha1": + fn = CryptEncoderSSHA1(e.salt) + case "sha256": + fn = CryptEncoderSHA256 + case "ssha256": + fn = CryptEncoderSSHA256(e.salt) + case "sha384": + fn = CryptEncoderSHA384 + case "ssha384": + fn = CryptEncoderSSHA384(e.salt) + case "sha512": + fn = CryptEncoderSHA512 + case "ssha512": + fn = CryptEncoderSSHA512(e.salt) + } + + h := fn([]byte("admin"), nil) + if strings.Compare(fmt.Sprintf("%x", h), e.expected) != 0 { + t.Fatalf("Invalid %s hash: expected: %s; got: %x", strings.ToUpper(e.enc), e.expected, h) + } + } +} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go index f9e08e1..43e6418 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go @@ -3,6 +3,7 @@ // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. +// +build cgo // +build go1.8 package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go index 44fc4df..741ed90 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go @@ -80,7 +80,6 @@ func randStringBytes(n int) string { } func initDatabase(t *testing.T, db *sql.DB, rowCount int64) { - t.Logf("Executing db initializing statements") for _, query := range testTableStatements { _, err := db.Exec(query) if err != nil { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go index e4557e6..26af573 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go @@ -2,6 +2,7 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. + // +build libsqlite3 package sqlite3 @@ -10,6 +11,7 @@ package sqlite3 #cgo CFLAGS: -DUSE_LIBSQLITE3 #cgo linux LDFLAGS: -lsqlite3 #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 +#cgo openbsd LDFLAGS: -lsqlite3 #cgo solaris LDFLAGS: -lsqlite3 */ import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go index bb7e25f..e73982a 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go @@ -2,6 +2,7 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. + // +build !sqlite_omit_load_extension package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go similarity index 99% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go index c7b3bfe..7ea3294 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go @@ -2,6 +2,7 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. + // +build sqlite_omit_load_extension package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go new file mode 100644 index 0000000..c92e817 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_allow_uri_authority + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go new file mode 100644 index 0000000..89947cd --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go @@ -0,0 +1,16 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . + +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build !windows +// +build sqlite_app_armor + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go new file mode 100644 index 0000000..fd4f5a7 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_foreign_keys + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1 +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_fts3_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go similarity index 100% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_fts3_test.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_fts5.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go similarity index 90% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_fts5.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go index 0e65d69..fa98400 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_fts5.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go @@ -2,7 +2,8 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build fts5 + +// +build sqlite_fts5 fts5 package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go similarity index 63% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go index e960626..000777f 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go @@ -2,12 +2,16 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build icu + +// +build sqlite_icu icu package sqlite3 /* #cgo LDFLAGS: -licuuc -licui18n #cgo CFLAGS: -DSQLITE_ENABLE_ICU +#cgo darwin CFLAGS: -I/usr/local/opt/icu4c/include +#cgo darwin LDFLAGS: -L/usr/local/opt/icu4c/lib +#cgo openbsd LDFLAGS: -lsqlite3 */ import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go new file mode 100644 index 0000000..10d4433 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . + +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_introspect + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_json1.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go similarity index 85% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_json1.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go index a7b2473..47d3599 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_json1.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go @@ -2,7 +2,8 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build json1 + +// +build sqlite_json sqlite_json1 json1 package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go new file mode 100644 index 0000000..0e2f280 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_secure_delete + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_SECURE_DELETE=1 +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go new file mode 100644 index 0000000..8f86b21 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_secure_delete_fast + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go new file mode 100644 index 0000000..3a34c12 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_stat4 + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_ENABLE_STAT4 +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go new file mode 100644 index 0000000..94203b3 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go @@ -0,0 +1,289 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_userauth + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION +#cgo LDFLAGS: -lm +#ifndef USE_LIBSQLITE3 +#include +#else +#include +#endif +#include + +static int +_sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW) +{ + return sqlite3_user_authenticate(db, zUsername, aPW, nPW); +} + +static int +_sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) +{ + return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin); +} + +static int +_sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) +{ + return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin); +} + +static int +_sqlite3_user_delete(sqlite3* db, const char* zUsername) +{ + return sqlite3_user_delete(db, zUsername); +} + +static int +_sqlite3_auth_enabled(sqlite3* db) +{ + int exists = -1; + + sqlite3_stmt *stmt; + sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL); + + while ( sqlite3_step(stmt) == SQLITE_ROW) { + exists = sqlite3_column_int(stmt, 0); + } + + sqlite3_finalize(stmt); + + return exists; +} +*/ +import "C" +import ( + "errors" + "unsafe" +) + +const ( + SQLITE_AUTH = C.SQLITE_AUTH +) + +var ( + ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized") + ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required") +) + +// Authenticate will perform an authentication of the provided username +// and password against the database. +// +// If a database contains the SQLITE_USER table, then the +// call to Authenticate must be invoked with an +// appropriate username and password prior to enable read and write +//access to the database. +// +// Return SQLITE_OK on success or SQLITE_ERROR if the username/password +// combination is incorrect or unknown. +// +// If the SQLITE_USER table is not present in the database file, then +// this interface is a harmless no-op returnning SQLITE_OK. +func (c *SQLiteConn) Authenticate(username, password string) error { + rv := c.authenticate(username, password) + switch rv { + case C.SQLITE_ERROR, C.SQLITE_AUTH: + return ErrUnauthorized + case C.SQLITE_OK: + return nil + default: + return c.lastError() + } +} + +// authenticate provides the actual authentication to SQLite. +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authenticate(username, password string) int { + // Allocate C Variables + cuser := C.CString(username) + cpass := C.CString(password) + + // Free C Variables + defer func() { + C.free(unsafe.Pointer(cuser)) + C.free(unsafe.Pointer(cpass)) + }() + + return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))) +} + +// AuthUserAdd can be used (by an admin user only) +// to create a new user. When called on a no-authentication-required +// database, this routine converts the database into an authentication- +// required database, automatically makes the added user an +// administrator, and logs in the current connection as that user. +// The AuthUserAdd only works for the "main" database, not +// for any ATTACH-ed databases. Any call to AuthUserAdd by a +// non-admin user results in an error. +func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { + isAdmin := 0 + if admin { + isAdmin = 1 + } + + rv := c.authUserAdd(username, password, isAdmin) + switch rv { + case C.SQLITE_ERROR, C.SQLITE_AUTH: + return ErrAdminRequired + case C.SQLITE_OK: + return nil + default: + return c.lastError() + } +} + +// authUserAdd enables the User Authentication if not enabled. +// Otherwise it will add a user. +// +// When user authentication is already enabled then this function +// can only be called by an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { + // Allocate C Variables + cuser := C.CString(username) + cpass := C.CString(password) + + // Free C Variables + defer func() { + C.free(unsafe.Pointer(cuser)) + C.free(unsafe.Pointer(cpass)) + }() + + return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) +} + +// AuthUserChange can be used to change a users +// login credentials or admin privilege. Any user can change their own +// login credentials. Only an admin user can change another users login +// credentials or admin privilege setting. No user may change their own +// admin privilege setting. +func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { + isAdmin := 0 + if admin { + isAdmin = 1 + } + + rv := c.authUserChange(username, password, isAdmin) + switch rv { + case C.SQLITE_ERROR, C.SQLITE_AUTH: + return ErrAdminRequired + case C.SQLITE_OK: + return nil + default: + return c.lastError() + } +} + +// authUserChange allows to modify a user. +// Users can change their own password. +// +// Only admins can change passwords for other users +// and modify the admin flag. +// +// The admin flag of the current logged in user cannot be changed. +// THis ensures that their is always an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserChange(username, password string, admin int) int { + // Allocate C Variables + cuser := C.CString(username) + cpass := C.CString(password) + + // Free C Variables + defer func() { + C.free(unsafe.Pointer(cuser)) + C.free(unsafe.Pointer(cpass)) + }() + + return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) +} + +// AuthUserDelete can be used (by an admin user only) +// to delete a user. The currently logged-in user cannot be deleted, +// which guarantees that there is always an admin user and hence that +// the database cannot be converted into a no-authentication-required +// database. +func (c *SQLiteConn) AuthUserDelete(username string) error { + rv := c.authUserDelete(username) + switch rv { + case C.SQLITE_ERROR, C.SQLITE_AUTH: + return ErrAdminRequired + case C.SQLITE_OK: + return nil + default: + return c.lastError() + } +} + +// authUserDelete can be used to delete a user. +// +// This function can only be executed by an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserDelete(username string) int { + // Allocate C Variables + cuser := C.CString(username) + + // Free C Variables + defer func() { + C.free(unsafe.Pointer(cuser)) + }() + + return int(C._sqlite3_user_delete(c.db, cuser)) +} + +// AuthEnabled checks if the database is protected by user authentication +func (c *SQLiteConn) AuthEnabled() (exists bool) { + rv := c.authEnabled() + if rv == 1 { + exists = true + } + + return +} + +// authEnabled perform the actual check for user authentication. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// 0 - Disabled +// 1 - Enabled +func (c *SQLiteConn) authEnabled() int { + return int(C._sqlite3_auth_enabled(c.db)) +} + +// EOF diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go new file mode 100644 index 0000000..302cd57 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go @@ -0,0 +1,152 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build !sqlite_userauth + +package sqlite3 + +import ( + "C" +) + +// Authenticate will perform an authentication of the provided username +// and password against the database. +// +// If a database contains the SQLITE_USER table, then the +// call to Authenticate must be invoked with an +// appropriate username and password prior to enable read and write +//access to the database. +// +// Return SQLITE_OK on success or SQLITE_ERROR if the username/password +// combination is incorrect or unknown. +// +// If the SQLITE_USER table is not present in the database file, then +// this interface is a harmless no-op returnning SQLITE_OK. +func (c *SQLiteConn) Authenticate(username, password string) error { + // NOOP + return nil +} + +// authenticate provides the actual authentication to SQLite. +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authenticate(username, password string) int { + // NOOP + return 0 +} + +// AuthUserAdd can be used (by an admin user only) +// to create a new user. When called on a no-authentication-required +// database, this routine converts the database into an authentication- +// required database, automatically makes the added user an +// administrator, and logs in the current connection as that user. +// The AuthUserAdd only works for the "main" database, not +// for any ATTACH-ed databases. Any call to AuthUserAdd by a +// non-admin user results in an error. +func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { + // NOOP + return nil +} + +// authUserAdd enables the User Authentication if not enabled. +// Otherwise it will add a user. +// +// When user authentication is already enabled then this function +// can only be called by an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { + // NOOP + return 0 +} + +// AuthUserChange can be used to change a users +// login credentials or admin privilege. Any user can change their own +// login credentials. Only an admin user can change another users login +// credentials or admin privilege setting. No user may change their own +// admin privilege setting. +func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { + // NOOP + return nil +} + +// authUserChange allows to modify a user. +// Users can change their own password. +// +// Only admins can change passwords for other users +// and modify the admin flag. +// +// The admin flag of the current logged in user cannot be changed. +// THis ensures that their is always an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserChange(username, password string, admin int) int { + // NOOP + return 0 +} + +// AuthUserDelete can be used (by an admin user only) +// to delete a user. The currently logged-in user cannot be deleted, +// which guarantees that there is always an admin user and hence that +// the database cannot be converted into a no-authentication-required +// database. +func (c *SQLiteConn) AuthUserDelete(username string) error { + // NOOP + return nil +} + +// authUserDelete can be used to delete a user. +// +// This function can only be executed by an admin. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// C.SQLITE_OK (0) +// C.SQLITE_ERROR (1) +// C.SQLITE_AUTH (23) +func (c *SQLiteConn) authUserDelete(username string) int { + // NOOP + return 0 +} + +// AuthEnabled checks if the database is protected by user authentication +func (c *SQLiteConn) AuthEnabled() (exists bool) { + // NOOP + return false +} + +// authEnabled perform the actual check for user authentication. +// +// This is not exported for usage in Go. +// It is however exported for usage within SQL by the user. +// +// Returns: +// 0 - Disabled +// 1 - Enabled +func (c *SQLiteConn) authEnabled() int { + // NOOP + return 0 +} + +// EOF diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go new file mode 100644 index 0000000..b4ac4a9 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go @@ -0,0 +1,619 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_userauth + +package sqlite3 + +import ( + "database/sql" + "fmt" + "os" + "testing" +) + +var ( + conn *SQLiteConn + create func(t *testing.T, username, password string) (file string, err error) + createWithCrypt func(t *testing.T, username, password, crypt, salt string) (file string, err error) + connect func(t *testing.T, f string, username, password string) (file string, db *sql.DB, c *SQLiteConn, err error) + connectWithCrypt func(t *testing.T, f string, username, password string, crypt string, salt string) (file string, db *sql.DB, c *SQLiteConn, err error) + authEnabled func(db *sql.DB) (exists bool, err error) + addUser func(db *sql.DB, username, password string, admin int) (rv int, err error) + userExists func(db *sql.DB, username string) (rv int, err error) + isAdmin func(db *sql.DB, username string) (rv bool, err error) + modifyUser func(db *sql.DB, username, password string, admin int) (rv int, err error) + deleteUser func(db *sql.DB, username string) (rv int, err error) +) + +func init() { + // Create database connection + sql.Register("sqlite3_with_conn", + &SQLiteDriver{ + ConnectHook: func(c *SQLiteConn) error { + conn = c + return nil + }, + }) + + create = func(t *testing.T, username, password string) (file string, err error) { + var db *sql.DB + file, db, _, err = connect(t, "", username, password) + db.Close() + return + } + + createWithCrypt = func(t *testing.T, username, password, crypt, salt string) (file string, err error) { + var db *sql.DB + file, db, _, err = connectWithCrypt(t, "", "admin", "admin", crypt, salt) + db.Close() + return + } + + connect = func(t *testing.T, f string, username, password string) (file string, db *sql.DB, c *SQLiteConn, err error) { + conn = nil // Clear connection + file = f // Copy provided file (f) => file + if file == "" { + // Create dummy file + file = TempFilename(t) + } + + db, err = sql.Open("sqlite3_with_conn", "file:"+file+fmt.Sprintf("?_auth&_auth_user=%s&_auth_pass=%s", username, password)) + if err != nil { + defer os.Remove(file) + return file, nil, nil, err + } + + // Dummy query to force connection and database creation + // Will return ErrUnauthorized (SQLITE_AUTH) if user authentication fails + if _, err = db.Exec("SELECT 1;"); err != nil { + defer os.Remove(file) + defer db.Close() + return file, nil, nil, err + } + c = conn + + return + } + + connectWithCrypt = func(t *testing.T, f string, username, password string, crypt string, salt string) (file string, db *sql.DB, c *SQLiteConn, err error) { + conn = nil // Clear connection + file = f // Copy provided file (f) => file + if file == "" { + // Create dummy file + file = TempFilename(t) + } + + db, err = sql.Open("sqlite3_with_conn", "file:"+file+fmt.Sprintf("?_auth&_auth_user=%s&_auth_pass=%s&_auth_crypt=%s&_auth_salt=%s", username, password, crypt, salt)) + if err != nil { + defer os.Remove(file) + return file, nil, nil, err + } + + // Dummy query to force connection and database creation + // Will return ErrUnauthorized (SQLITE_AUTH) if user authentication fails + if _, err = db.Exec("SELECT 1;"); err != nil { + defer os.Remove(file) + defer db.Close() + return file, nil, nil, err + } + c = conn + + return + } + + authEnabled = func(db *sql.DB) (exists bool, err error) { + err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists) + return + } + + addUser = func(db *sql.DB, username, password string, admin int) (rv int, err error) { + err = db.QueryRow("select auth_user_add(?, ?, ?);", username, password, admin).Scan(&rv) + return + } + + userExists = func(db *sql.DB, username string) (rv int, err error) { + err = db.QueryRow("select count(uname) from sqlite_user where uname=?", username).Scan(&rv) + return + } + + isAdmin = func(db *sql.DB, username string) (rv bool, err error) { + err = db.QueryRow("select isAdmin from sqlite_user where uname=?", username).Scan(&rv) + return + } + + modifyUser = func(db *sql.DB, username, password string, admin int) (rv int, err error) { + err = db.QueryRow("select auth_user_change(?, ?, ?);", username, password, admin).Scan(&rv) + return + } + + deleteUser = func(db *sql.DB, username string) (rv int, err error) { + err = db.QueryRow("select auth_user_delete(?);", username).Scan(&rv) + return + } +} + +func TestUserAuthCreateDatabase(t *testing.T) { + f, db, c, err := connect(t, "", "admin", "admin") + if err != nil && c == nil && db == nil { + t.Fatal(err) + } + defer db.Close() + defer os.Remove(f) + + enabled, err := authEnabled(db) + if err != nil || !enabled { + t.Fatalf("UserAuth not enabled: %s", err) + } + + e, err := userExists(db, "admin") + if err != nil { + t.Fatal(err) + } + if e != 1 { + t.Fatal("UserAuth: admin does not exists") + } + a, err := isAdmin(db, "admin") + if err != nil { + t.Fatal(err) + } + if !a { + t.Fatal("UserAuth: User is not administrator") + } +} + +func TestUserAuthLogin(t *testing.T) { + f1, err := create(t, "admin", "admin") + if err != nil { + t.Fatal(err) + } + defer os.Remove(f1) + + f2, db2, c2, err := connect(t, f1, "admin", "admin") + if err != nil { + t.Fatal(err) + } + defer db2.Close() + if f1 != f2 { + t.Fatal("UserAuth: Database file mismatch") + } + + // Test lower level authentication + err = c2.Authenticate("admin", "admin") + if err != nil { + t.Fatalf("UserAuth: *SQLiteConn.Authenticate() Failed: %s", err) + } + + // Test Login Failed + _, _, _, err = connect(t, f1, "admin", "invalid") + if err == nil { + t.Fatal("Login successful while expecting to fail") + } + if err != ErrUnauthorized { + t.Fatal(err) + } + err = c2.Authenticate("admin", "invalid") + if err == nil { + t.Fatal("Login successful while expecting to fail") + } + if err != ErrUnauthorized { + t.Fatal(err) + } +} + +func TestUserAuthAddAdmin(t *testing.T) { + f, db, c, err := connect(t, "", "admin", "admin") + if err != nil && c == nil && db == nil { + t.Fatal(err) + } + defer db.Close() + defer os.Remove(f) + + // Add Admin User through SQL call + rv, err := addUser(db, "admin2", "admin2", 1) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Check if user was created + exists, err := userExists(db, "admin2") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'admin2' does not exists") + } + + // Check if user was created as an Administrator + admin, err := isAdmin(db, "admin2") + if err != nil { + t.Fatal(err) + } + if !admin { + t.Fatal("UserAuth: 'admin2' is not administrator") + } + + // Test *SQLiteConn + err = c.AuthUserAdd("admin3", "admin3", true) + if err != nil { + t.Fatal(err) + } + + // Check if user was created + exists, err = userExists(db, "admin2") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'admin3' does not exists") + } + + // Check if the user was created as an Administrator + admin, err = isAdmin(db, "admin3") + if err != nil { + t.Fatal(err) + } + if !admin { + t.Fatal("UserAuth: 'admin3' is not administrator") + } +} + +func TestUserAuthAddUser(t *testing.T) { + f1, db1, c, err := connect(t, "", "admin", "admin") + if err != nil && c == nil && db == nil { + t.Fatal(err) + } + defer os.Remove(f1) + + // Add user through SQL call + rv, err := addUser(db1, "user", "user", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Check if user was created + exists, err := userExists(db1, "user") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'user' does not exists") + } + + // Check if user was created as an Administrator + admin, err := isAdmin(db1, "user") + if err != nil { + t.Fatal(err) + } + if admin { + t.Fatal("UserAuth: 'user' is administrator") + } + + // Test *SQLiteConn + err = c.AuthUserAdd("user2", "user2", false) + if err != nil { + t.Fatal(err) + } + + // Check if user was created + exists, err = userExists(db1, "user2") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'user2' does not exists") + } + + // Check if the user was created as an Administrator + admin, err = isAdmin(db1, "user2") + if err != nil { + t.Fatal(err) + } + if admin { + t.Fatal("UserAuth: 'user2' is administrator") + } + + // Reconnect as normal user + db1.Close() + _, db2, c2, err := connect(t, f1, "user", "user") + if err != nil { + t.Fatal(err) + } + defer db2.Close() + + // Try to create admin user while logged in as normal user + rv, err = addUser(db2, "admin2", "admin2", 1) + if err != nil { + t.Fatal(err) + } + if rv != SQLITE_AUTH { + t.Fatal("Created admin user while not allowed") + } + + err = c2.AuthUserAdd("admin3", "admin3", true) + if err != ErrAdminRequired { + t.Fatal("Created admin user while not allowed") + } + + // Try to create normal user while logged in as normal user + rv, err = addUser(db2, "user3", "user3", 0) + if err != nil { + t.Fatal(err) + } + if rv != SQLITE_AUTH { + t.Fatal("Created user while not allowed") + } + + err = c2.AuthUserAdd("user4", "user4", false) + if err != ErrAdminRequired { + t.Fatal("Created user while not allowed") + } +} + +func TestUserAuthModifyUser(t *testing.T) { + f1, db1, c1, err := connect(t, "", "admin", "admin") + if err != nil && c1 == nil && db == nil { + t.Fatal(err) + } + defer os.Remove(f1) + + // Modify Password for current logged in admin + // through SQL + rv, err := modifyUser(db1, "admin", "admin2", 1) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to modify password for admin") + } + + // Modify password for current logged in admin + // through *SQLiteConn + err = c1.AuthUserChange("admin", "admin3", true) + if err != nil { + t.Fatal(err) + } + + // Modify Administrator Flag + // Because we are current logged in as 'admin' + // Changing our own admin flag should fail. + rv, err = modifyUser(db1, "admin", "admin3", 0) + if err != nil { + t.Fatal(err) + } + if rv != SQLITE_AUTH { + t.Fatal("Successfully changed admin flag while not allowed") + } + + // Modify admin flag through (*SQLiteConn) + // Because we are current logged in as 'admin' + // Changing our own admin flag should fail. + err = c1.AuthUserChange("admin", "admin3", false) + if err != ErrAdminRequired { + t.Fatal("Successfully changed admin flag while not allowed") + } + + // Add normal user + rv, err = addUser(db1, "user", "password", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + rv, err = addUser(db1, "user2", "user2", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Modify other user password and flag through SQL + rv, err = modifyUser(db1, "user", "pass", 1) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to modify password for user") + } + + // Modify other user password and flag through *SQLiteConn + err = c1.AuthUserChange("user", "newpass", false) + if err != nil { + t.Fatal(err) + } + + // Disconnect database for reconnect + db1.Close() + _, db2, c2, err := connect(t, f1, "user", "newpass") + if err != nil { + t.Fatal(err) + } + defer db2.Close() + + // Modify other user password through SQL + rv, err = modifyUser(db2, "user2", "newpass", 0) + if err != nil { + t.Fatal(err) + } + if rv != SQLITE_AUTH { + t.Fatal("Password change succesful while not allowed") + } + + // Modify other user password and flag through *SQLiteConn + err = c2.AuthUserChange("user2", "invalid", false) + if err != ErrAdminRequired { + t.Fatal("Password change succesful while not allowed") + } +} + +func TestUserAuthDeleteUser(t *testing.T) { + f1, db1, c, err := connect(t, "", "admin", "admin") + if err != nil && c == nil && db == nil { + t.Fatal(err) + } + defer os.Remove(f1) + + // Add Admin User 2 + rv, err := addUser(db1, "admin2", "admin2", 1) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + rv, err = addUser(db1, "admin3", "admin3", 1) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Check if user was created + exists, err := userExists(db1, "admin2") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'admin2' does not exists") + } + + exists, err = userExists(db1, "admin3") + if err != nil { + t.Fatal(err) + } + if exists != 1 { + t.Fatal("UserAuth: 'admin2' does not exists") + } + + // Delete user through SQL + rv, err = deleteUser(db1, "admin2") + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to delete admin2") + } + + // Verify user admin2 deleted + exists, err = userExists(db1, "admin2") + if err != nil { + t.Fatal(err) + } + if exists != 0 { + t.Fatal("UserAuth: 'admin2' still exists") + } + + // Delete user through *SQLiteConn + rv, err = deleteUser(db1, "admin3") + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to delete admin3") + } + + // Verify user admin3 deleted + exists, err = userExists(db1, "admin3") + if err != nil { + t.Fatal(err) + } + if exists != 0 { + t.Fatal("UserAuth: 'admin3' still exists") + } + + // Add normal user for reconnect and privileges check + rv, err = addUser(db1, "reconnect", "reconnect", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Add normal user for deletion through SQL + rv, err = addUser(db1, "user", "user", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + rv, err = addUser(db1, "user2", "user2", 0) + if err != nil { + t.Fatal(err) + } + if rv != 0 { + t.Fatal("Failed to add user") + } + + // Close database for reconnect + db1.Close() + + // Reconnect as normal user + _, db2, c2, err := connect(t, f1, "reconnect", "reconnect") + if err != nil { + t.Fatal(err) + } + defer db2.Close() + + // Delete user while logged in as normal user + // through SQL + rv, err = deleteUser(db2, "user") + if err != nil { + t.Fatal(err) + } + if rv != SQLITE_AUTH { + t.Fatal("Successfully deleted user wthout proper privileges") + } + + // Delete user while logged in as normal user + // through *SQLiteConn + err = c2.AuthUserDelete("user2") + if err != ErrAdminRequired { + t.Fatal("Successfully deleted user wthout proper privileges") + } +} + +func TestUserAuthEncoders(t *testing.T) { + cases := map[string]string{ + "sha1": "", + "ssha1": "salted", + "sha256": "", + "ssha256": "salted", + "sha384": "", + "ssha384": "salted", + "sha512": "", + "ssha512": "salted", + } + + for enc, salt := range cases { + f, err := createWithCrypt(t, "admin", "admin", enc, salt) + if err != nil { + t.Fatal(err) + } + defer os.Remove(f) + + _, db, _, err := connectWithCrypt(t, f, "admin", "admin", enc, salt) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if e, err := authEnabled(db); err != nil && !e { + t.Fatalf("UserAuth (%s) not enabled %s", enc, err) + } + } +} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go new file mode 100644 index 0000000..a202c80 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_vacuum_full + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1 +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go new file mode 100644 index 0000000..62bbf50 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go @@ -0,0 +1,15 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_vacuum_incr + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2 +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go similarity index 98% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go index 8bef291..73d66c0 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go @@ -2,14 +2,18 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build vtable + +// +build sqlite_vtable vtable package sqlite3 /* #cgo CFLAGS: -std=gnu99 -#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE -#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61 +#cgo CFLAGS: -DSQLITE_ENABLE_RTREE +#cgo CFLAGS: -DSQLITE_THREADSAFE +#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 +#cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS +#cgo CFLAGS: -DSQLITE_ENABLE_FTS4_UNICODE61 #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15 #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1 #cgo CFLAGS: -Wno-deprecated-declarations diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go similarity index 99% rename from vendor/github.com/mattn/go-sqlite3/sqlite3_vtable_test.go rename to vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go index ce6a48c..d196c75 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable_test.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go @@ -2,7 +2,8 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build vtable + +// +build sqlite_vtable vtable package sqlite3 diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go index f721b5e..086ed43 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go @@ -2,6 +2,7 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. + // +build !windows package sqlite3 @@ -9,6 +10,5 @@ package sqlite3 /* #cgo CFLAGS: -I. #cgo linux LDFLAGS: -ldl -#cgo solaris LDFLAGS: -lc */ import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go new file mode 100644 index 0000000..40b2b2f --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go @@ -0,0 +1,14 @@ +// Copyright (C) 2018 Yasuhiro Matsumoto . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build solaris + +package sqlite3 + +/* +#cgo CFLAGS: -D__EXTENSIONS__=1 +#cgo LDFLAGS: -lc +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go index 84ecb5a..75d8f52 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go @@ -231,6 +231,55 @@ func TestInsert(t *testing.T) { } } +func TestUpsert(t *testing.T) { + _, n, _ := Version() + if !(n >= 3024000) { + t.Skip("UPSERT requires sqlite3 => 3.24.0") + } + tempFilename := TempFilename(t) + defer os.Remove(tempFilename) + db, err := sql.Open("sqlite3", tempFilename) + if err != nil { + t.Fatal("Failed to open database:", err) + } + defer db.Close() + + _, err = db.Exec("drop table foo") + _, err = db.Exec("create table foo (name string primary key, counter integer)") + if err != nil { + t.Fatal("Failed to create table:", err) + } + + for i := 0; i < 10; i++ { + res, err := db.Exec("insert into foo(name, counter) values('key', 1) on conflict (name) do update set counter=counter+1") + if err != nil { + t.Fatal("Failed to upsert record:", err) + } + affected, _ := res.RowsAffected() + if affected != 1 { + t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) + } + } + rows, err := db.Query("select name, counter from foo") + if err != nil { + t.Fatal("Failed to select records:", err) + } + defer rows.Close() + + rows.Next() + + var resultName string + var resultCounter int + rows.Scan(&resultName, &resultCounter) + if resultName != "key" { + t.Errorf("Expected %s for fetched result, but %s:", "key", resultName) + } + if resultCounter != 10 { + t.Errorf("Expected %d for fetched result, but %d:", 10, resultCounter) + } + +} + func TestUpdate(t *testing.T) { tempFilename := TempFilename(t) defer os.Remove(tempFilename) @@ -563,7 +612,7 @@ func TestBoolean(t *testing.T) { t.Fatalf("Expected 1 row but %v", counter) } - if id != 1 && fbool != true { + if id != 1 && !fbool { t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool) } @@ -585,7 +634,7 @@ func TestBoolean(t *testing.T) { t.Fatalf("Expected 1 row but %v", counter) } - if id != 2 && fbool != false { + if id != 2 && fbool { t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool) } @@ -1580,6 +1629,25 @@ func TestNilAndEmptyBytes(t *testing.T) { } } +func TestInsertNilByteSlice(t *testing.T) { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err := db.Exec("create table blob_not_null (b blob not null)"); err != nil { + t.Fatal(err) + } + var nilSlice []byte + if _, err := db.Exec("insert into blob_not_null (b) values (?)", nilSlice); err == nil { + t.Fatal("didn't expect INSERT to 'not null' column with a nil []byte slice to work") + } + zeroLenSlice := []byte{} + if _, err := db.Exec("insert into blob_not_null (b) values (?)", zeroLenSlice); err != nil { + t.Fatal("failed to insert zero-length slice") + } +} + var customFunctionOnce sync.Once func BenchmarkCustomFunctions(b *testing.B) { @@ -1591,10 +1659,7 @@ func BenchmarkCustomFunctions(b *testing.B) { sql.Register("sqlite3_BenchmarkCustomFunctions", &SQLiteDriver{ ConnectHook: func(conn *SQLiteConn) error { // Impure function to force sqlite to reexecute it each time. - if err := conn.RegisterFunc("custom_add", customAdd, false); err != nil { - return err - } - return nil + return conn.RegisterFunc("custom_add", customAdd, false) }, }) }) @@ -1663,6 +1728,7 @@ var testTables = []string{"foo", "bar", "t", "bench"} var tests = []testing.InternalTest{ {Name: "TestResult", F: testResult}, {Name: "TestBlobs", F: testBlobs}, + {Name: "TestMultiBlobs", F: testMultiBlobs}, {Name: "TestManyQueryRow", F: testManyQueryRow}, {Name: "TestTxQuery", F: testTxQuery}, {Name: "TestPreparedStmt", F: testPreparedStmt}, @@ -1701,7 +1767,7 @@ func (db *TestDB) tearDown() { // q replaces ? parameters if needed func (db *TestDB) q(sql string) string { switch db.dialect { - case POSTGRESQL: // repace with $1, $2, .. + case POSTGRESQL: // replace with $1, $2, .. qrx := regexp.MustCompile(`\?`) n := 0 return qrx.ReplaceAllStringFunc(sql, func(string) string { @@ -1818,6 +1884,56 @@ func testBlobs(t *testing.T) { } } +func testMultiBlobs(t *testing.T) { + db.tearDown() + db.mustExec("create table foo (id integer primary key, bar " + db.blobType(16) + ")") + var blob0 = []byte{0, 1, 2, 3, 4, 5, 6, 7} + db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 0, blob0) + var blob1 = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 1, blob1) + + r, err := db.Query(db.q("select bar from foo order by id")) + if err != nil { + t.Fatal(err) + } + defer r.Close() + if !r.Next() { + if r.Err() != nil { + t.Fatal(err) + } + t.Fatal("expected one rows") + } + + want0 := fmt.Sprintf("%x", blob0) + b0 := make([]byte, 8) + err = r.Scan(&b0) + if err != nil { + t.Fatal(err) + } + got0 := fmt.Sprintf("%x", b0) + + if !r.Next() { + if r.Err() != nil { + t.Fatal(err) + } + t.Fatal("expected one rows") + } + + want1 := fmt.Sprintf("%x", blob1) + b1 := make([]byte, 16) + err = r.Scan(&b1) + if err != nil { + t.Fatal(err) + } + got1 := fmt.Sprintf("%x", b1) + if got0 != want0 { + t.Errorf("for []byte, got %q; want %q", got0, want0) + } + if got1 != want1 { + t.Errorf("for []byte, got %q; want %q", got1, want1) + } +} + // testManyQueryRow is test for many query row func testManyQueryRow(t *testing.T) { if testing.Short() { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go index ece6035..ee93a0f 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go @@ -2,7 +2,8 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. -// +build trace + +// +build sqlite_trace trace package sqlite3 @@ -28,10 +29,10 @@ import ( // Trace... constants identify the possible events causing callback invocation. // Values are same as the corresponding SQLite Trace Event Codes. const ( - TraceStmt = C.SQLITE_TRACE_STMT - TraceProfile = C.SQLITE_TRACE_PROFILE - TraceRow = C.SQLITE_TRACE_ROW - TraceClose = C.SQLITE_TRACE_CLOSE + TraceStmt = uint32(C.SQLITE_TRACE_STMT) + TraceProfile = uint32(C.SQLITE_TRACE_PROFILE) + TraceRow = uint32(C.SQLITE_TRACE_ROW) + TraceClose = uint32(C.SQLITE_TRACE_CLOSE) ) type TraceInfo struct { @@ -71,7 +72,7 @@ type TraceUserCallback func(TraceInfo) int type TraceConfig struct { Callback TraceUserCallback - EventMask C.uint + EventMask uint32 WantExpandedSQL bool } @@ -105,6 +106,8 @@ func traceCallbackTrampoline( // Parameter named 'X' in SQLite docs (eXtra event data?): xValue unsafe.Pointer) C.int { + eventCode := uint32(traceEventCode) + if ctx == nil { panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode)) } @@ -114,7 +117,7 @@ func traceCallbackTrampoline( var traceConf TraceConfig var found bool - if traceEventCode == TraceClose { + if eventCode == TraceClose { // clean up traceMap: 'pop' means get and delete traceConf, found = popTraceMapping(connHandle) } else { @@ -123,16 +126,16 @@ func traceCallbackTrampoline( if !found { panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)", - connHandle, traceEventCode)) + connHandle, eventCode)) } var info TraceInfo - info.EventCode = uint32(traceEventCode) + info.EventCode = eventCode info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0) info.ConnHandle = connHandle - switch traceEventCode { + switch eventCode { case TraceStmt: info.StmtHandle = uintptr(p) @@ -183,7 +186,7 @@ func traceCallbackTrampoline( // registering this callback trampoline with SQLite --- for cleanup. // In the future there may be more events forced to "selected" in SQLite // for the driver's needs. - if traceConf.EventMask&traceEventCode == 0 { + if traceConf.EventMask&eventCode == 0 { return 0 } diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go new file mode 100644 index 0000000..1971a48 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go @@ -0,0 +1,39 @@ +// Copyright (C) 2018 G.J.R. Timmer . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build cgo + +package sqlite3 + +// usleep is a function available on *nix based systems. +// This function is not present in Windows. +// Windows has a sleep function but this works with seconds +// and not with microseconds as usleep. +// +// This code should improve performance on windows because +// without the presence of usleep SQLite waits 1 second. +// +// Source: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa + +/* +#include + +void usleep(__int64 usec) +{ + HANDLE timer; + LARGE_INTEGER ft; + + // Convert to 100 nanosecond interval, negative value indicates relative time + ft.QuadPart = -(10*usec); + + timer = CreateWaitableTimer(NULL, TRUE, NULL); + SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); +} +*/ +import "C" + +// EOF diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go index 163e8f7..4222e7f 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go @@ -2,13 +2,17 @@ // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. + // +build windows package sqlite3 /* -#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe -#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T +#cgo CFLAGS: -I. +#cgo CFLAGS: -fno-stack-check +#cgo CFLAGS: -fno-stack-protector +#cgo CFLAGS: -mno-stack-arg-probe #cgo LDFLAGS: -lmingwex -lmingw32 +#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T */ import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h b/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h index d5fd905..913e72d 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h @@ -293,6 +293,24 @@ struct sqlite3_api_routines { int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); void *(*value_pointer)(sqlite3_value*,const char*); + int (*vtab_nochange)(sqlite3_context*); + int (*value_nochange)(sqlite3_value*); + const char *(*vtab_collation)(sqlite3_index_info*,int); + /* Version 3.24.0 and later */ + int (*keyword_count)(void); + int (*keyword_name)(int,const char**,int*); + int (*keyword_check)(const char*,int); + sqlite3_str *(*str_new)(sqlite3*); + char *(*str_finish)(sqlite3_str*); + void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); + void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); + void (*str_append)(sqlite3_str*, const char *zIn, int N); + void (*str_appendall)(sqlite3_str*, const char *zIn); + void (*str_appendchar)(sqlite3_str*, int N, char C); + void (*str_reset)(sqlite3_str*); + int (*str_errcode)(sqlite3_str*); + int (*str_length)(sqlite3_str*); + char *(*str_value)(sqlite3_str*); }; /* @@ -559,6 +577,25 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_bind_pointer sqlite3_api->bind_pointer #define sqlite3_result_pointer sqlite3_api->result_pointer #define sqlite3_value_pointer sqlite3_api->value_pointer +/* Version 3.22.0 and later */ +#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange +#define sqlite3_value_nochange sqlite3_api->value_nochange +#define sqlite3_vtab_collation sqlite3_api->vtab_collation +/* Version 3.24.0 and later */ +#define sqlite3_keyword_count sqlite3_api->keyword_count +#define sqlite3_keyword_name sqlite3_api->keyword_name +#define sqlite3_keyword_check sqlite3_api->keyword_check +#define sqlite3_str_new sqlite3_api->str_new +#define sqlite3_str_finish sqlite3_api->str_finish +#define sqlite3_str_appendf sqlite3_api->str_appendf +#define sqlite3_str_vappendf sqlite3_api->str_vappendf +#define sqlite3_str_append sqlite3_api->str_append +#define sqlite3_str_appendall sqlite3_api->str_appendall +#define sqlite3_str_appendchar sqlite3_api->str_appendchar +#define sqlite3_str_reset sqlite3_api->str_reset +#define sqlite3_str_errcode sqlite3_api->str_errcode +#define sqlite3_str_length sqlite3_api->str_length +#define sqlite3_str_value sqlite3_api->str_value #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/vendor/github.com/mattn/go-sqlite3/static_mock.go b/vendor/github.com/mattn/go-sqlite3/static_mock.go new file mode 100644 index 0000000..48629d1 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/static_mock.go @@ -0,0 +1,21 @@ +// +build !cgo + +package sqlite3 + +import ( + "database/sql" + "database/sql/driver" + "errors" +) + +func init() { + sql.Register("sqlite3", &SQLiteDriverMock{}) +} + +type SQLiteDriverMock struct{} + +var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub") + +func (SQLiteDriverMock) Open(s string) (driver.Conn, error) { + return nil, errorMsg +} diff --git a/vendor/github.com/mattn/go-sqlite3/tool/upgrade.go b/vendor/github.com/mattn/go-sqlite3/tool/upgrade.go deleted file mode 100644 index 94ed39d..0000000 --- a/vendor/github.com/mattn/go-sqlite3/tool/upgrade.go +++ /dev/null @@ -1,111 +0,0 @@ -// +build ignore - -package main - -import ( - "archive/zip" - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "os" - "path" - "path/filepath" - "strings" - - "github.com/PuerkitoBio/goquery" -) - -func main() { - site := "https://www.sqlite.org/download.html" - fmt.Printf("scraping %v\n", site) - doc, err := goquery.NewDocument(site) - if err != nil { - log.Fatal(err) - } - var url string - doc.Find("a").Each(func(_ int, s *goquery.Selection) { - if url == "" && strings.HasPrefix(s.Text(), "sqlite-amalgamation-") { - url = "https://www.sqlite.org/2017/" + s.Text() - } - }) - if url == "" { - return - } - fmt.Printf("downloading %v\n", url) - resp, err := http.Get(url) - if err != nil { - log.Fatal(err) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - resp.Body.Close() - log.Fatal(err) - } - - fmt.Printf("extracting %v\n", path.Base(url)) - r, err := zip.NewReader(bytes.NewReader(b), resp.ContentLength) - if err != nil { - resp.Body.Close() - log.Fatal(err) - } - resp.Body.Close() - - for _, zf := range r.File { - var f *os.File - switch path.Base(zf.Name) { - case "sqlite3.c": - f, err = os.Create("sqlite3-binding.c") - case "sqlite3.h": - f, err = os.Create("sqlite3-binding.h") - case "sqlite3ext.h": - f, err = os.Create("sqlite3ext.h") - default: - continue - } - if err != nil { - log.Fatal(err) - } - zr, err := zf.Open() - if err != nil { - log.Fatal(err) - } - - _, err = io.WriteString(f, "#ifndef USE_LIBSQLITE3\n") - if err != nil { - zr.Close() - f.Close() - log.Fatal(err) - } - scanner := bufio.NewScanner(zr) - for scanner.Scan() { - text := scanner.Text() - if text == `#include "sqlite3.h"` { - text = `#include "sqlite3-binding.h"` - } - _, err = fmt.Fprintln(f, text) - if err != nil { - break - } - } - err = scanner.Err() - if err != nil { - zr.Close() - f.Close() - log.Fatal(err) - } - _, err = io.WriteString(f, "#else // USE_LIBSQLITE3\n // If users really want to link against the system sqlite3 we\n// need to make this file a noop.\n #endif") - if err != nil { - zr.Close() - f.Close() - log.Fatal(err) - } - zr.Close() - f.Close() - fmt.Printf("extracted %v\n", filepath.Base(f.Name())) - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/upgrade/package.go b/vendor/github.com/mattn/go-sqlite3/upgrade/package.go new file mode 100644 index 0000000..2b12a77 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/upgrade/package.go @@ -0,0 +1,7 @@ +// Package upgrade +// +// Dummy to ensure package can be loaded +// +// This file is to avoid the following error: +// can't load package: package go-sqlite3/upgrade: build constraints exclude all Go files in go-sqlite3\upgrade +package upgrade diff --git a/vendor/github.com/mattn/go-sqlite3/upgrade/upgrade.go b/vendor/github.com/mattn/go-sqlite3/upgrade/upgrade.go new file mode 100644 index 0000000..d800227 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/upgrade/upgrade.go @@ -0,0 +1,218 @@ +// +build !cgo +// +build upgrade + +package main + +import ( + "archive/zip" + "bufio" + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "time" + + "github.com/PuerkitoBio/goquery" +) + +func download(prefix string) (url string, content []byte, err error) { + year := time.Now().Year() + + site := "https://www.sqlite.org/download.html" + //fmt.Printf("scraping %v\n", site) + doc, err := goquery.NewDocument(site) + if err != nil { + log.Fatal(err) + } + + doc.Find("a").Each(func(_ int, s *goquery.Selection) { + if strings.HasPrefix(s.Text(), prefix) { + url = fmt.Sprintf("https://www.sqlite.org/%d/", year) + s.Text() + } + }) + + if url == "" { + return "", nil, fmt.Errorf("Unable to find prefix '%s' on sqlite.org", prefix) + } + + fmt.Printf("Downloading %v\n", url) + resp, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + // Ready Body Content + content, err = ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + if err != nil { + return "", nil, err + } + + return url, content, nil +} + +func mergeFile(src string, dst string) error { + defer func() error { + fmt.Printf("Removing: %s\n", src) + err := os.Remove(src) + + if err != nil { + return err + } + + return nil + }() + + // Open destination + fdst, err := os.OpenFile(dst, os.O_APPEND|os.O_WRONLY, 0666) + if err != nil { + return err + } + defer fdst.Close() + + // Read source content + content, err := ioutil.ReadFile(src) + if err != nil { + return err + } + + // Add Additional newline + if _, err := fdst.WriteString("\n"); err != nil { + return err + } + + fmt.Printf("Merging: %s into %s\n", src, dst) + if _, err = fdst.Write(content); err != nil { + return err + } + + return nil +} + +func main() { + fmt.Println("Go-SQLite3 Upgrade Tool") + + // Download Amalgamation + _, amalgamation, err := download("sqlite-amalgamation-") + if err != nil { + fmt.Println("Failed to download: sqlite-amalgamation; %s", err) + } + + // Download Source + _, source, err := download("sqlite-src-") + if err != nil { + fmt.Println("Failed to download: sqlite-src; %s", err) + } + + // Create Amalgamation Zip Reader + rAmalgamation, err := zip.NewReader(bytes.NewReader(amalgamation), int64(len(amalgamation))) + if err != nil { + log.Fatal(err) + } + + // Create Source Zip Reader + rSource, err := zip.NewReader(bytes.NewReader(source), int64(len(source))) + if err != nil { + log.Fatal(err) + } + + // Extract Amalgamation + for _, zf := range rAmalgamation.File { + var f *os.File + switch path.Base(zf.Name) { + case "sqlite3.c": + f, err = os.Create("sqlite3-binding.c") + case "sqlite3.h": + f, err = os.Create("sqlite3-binding.h") + case "sqlite3ext.h": + f, err = os.Create("sqlite3ext.h") + default: + continue + } + if err != nil { + log.Fatal(err) + } + zr, err := zf.Open() + if err != nil { + log.Fatal(err) + } + + _, err = io.WriteString(f, "#ifndef USE_LIBSQLITE3\n") + if err != nil { + zr.Close() + f.Close() + log.Fatal(err) + } + scanner := bufio.NewScanner(zr) + for scanner.Scan() { + text := scanner.Text() + if text == `#include "sqlite3.h"` { + text = `#include "sqlite3-binding.h"` + } + _, err = fmt.Fprintln(f, text) + if err != nil { + break + } + } + err = scanner.Err() + if err != nil { + zr.Close() + f.Close() + log.Fatal(err) + } + _, err = io.WriteString(f, "#else // USE_LIBSQLITE3\n // If users really want to link against the system sqlite3 we\n// need to make this file a noop.\n #endif") + if err != nil { + zr.Close() + f.Close() + log.Fatal(err) + } + zr.Close() + f.Close() + fmt.Printf("Extracted: %v\n", filepath.Base(f.Name())) + } + + //Extract Source + for _, zf := range rSource.File { + var f *os.File + switch path.Base(zf.Name) { + case "userauth.c": + f, err = os.Create("userauth.c") + case "sqlite3userauth.h": + f, err = os.Create("userauth.h") + default: + continue + } + if err != nil { + log.Fatal(err) + } + zr, err := zf.Open() + if err != nil { + log.Fatal(err) + } + + _, err = io.Copy(f, zr) + if err != nil { + log.Fatal(err) + } + + zr.Close() + f.Close() + fmt.Printf("extracted %v\n", filepath.Base(f.Name())) + } + + // Merge SQLite User Authentication into amalgamation + if err := mergeFile("userauth.c", "sqlite3-binding.c"); err != nil { + log.Fatal(err) + } + if err := mergeFile("userauth.h", "sqlite3-binding.h"); err != nil { + log.Fatal(err) + } + + os.Exit(0) +} diff --git a/vendor/github.com/miekg/dns/Makefile.release b/vendor/github.com/miekg/dns/Makefile.release index 4069eb0..8fb748e 100644 --- a/vendor/github.com/miekg/dns/Makefile.release +++ b/vendor/github.com/miekg/dns/Makefile.release @@ -49,3 +49,4 @@ commit: push: @echo Pushing release $(VERSION) to master git push --tags + git push diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index e6dbad2..1ad23c7 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -62,6 +62,8 @@ A not-so-up-to-date-list-that-may-be-actually-current: * https://dnssectest.net/ * https://dns.apebits.com * https://github.com/oif/apex +* https://github.com/jedisct1/dnscrypt-proxy +* https://github.com/jedisct1/rpdns Send pull request if you want to be listed here. diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go index 856b169..dd6b512 100644 --- a/vendor/github.com/miekg/dns/client.go +++ b/vendor/github.com/miekg/dns/client.go @@ -7,22 +7,27 @@ import ( "context" "crypto/tls" "encoding/binary" + "fmt" "io" + "io/ioutil" "net" + "net/http" "strings" "time" ) -const dnsTimeout time.Duration = 2 * time.Second -const tcpIdleTimeout time.Duration = 8 * time.Second +const ( + dnsTimeout time.Duration = 2 * time.Second + tcpIdleTimeout time.Duration = 8 * time.Second + + dohMimeType = "application/dns-message" +) // A Conn represents a connection to a DNS server. type Conn struct { net.Conn // a net.Conn holding the connection UDPSize uint16 // minimum receive buffer for UDP messages TsigSecret map[string]string // secret(s) for Tsig map[], zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) - rtt time.Duration - t time.Time tsigRequestMAC string } @@ -39,6 +44,7 @@ type Client struct { DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero + HTTPClient *http.Client // The http.Client to use for DNS-over-HTTPS TsigSecret map[string]string // secret(s) for Tsig map[], zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass group singleflight @@ -83,11 +89,10 @@ func (c *Client) Dial(address string) (conn *Conn, err error) { // create a new dialer with the appropriate timeout var d net.Dialer if c.Dialer == nil { - d = net.Dialer{} + d = net.Dialer{Timeout:c.getTimeoutForRequest(c.dialTimeout())} } else { d = net.Dialer(*c.Dialer) } - d.Timeout = c.getTimeoutForRequest(c.writeTimeout()) network := "udp" useTLS := false @@ -136,6 +141,11 @@ func (c *Client) Dial(address string) (conn *Conn, err error) { // attribute appropriately func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) { if !c.SingleInflight { + if c.Net == "https" { + // TODO(tmthrgd): pipe timeouts into exchangeDOH + return c.exchangeDOH(context.TODO(), m, address) + } + return c.exchange(m, address) } @@ -148,6 +158,11 @@ func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, er cl = cl1 } r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) { + if c.Net == "https" { + // TODO(tmthrgd): pipe timeouts into exchangeDOH + return c.exchangeDOH(context.TODO(), m, address) + } + return c.exchange(m, address) }) if r != nil && shared { @@ -177,8 +192,9 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro } co.TsigSecret = c.TsigSecret + t := time.Now() // write with the appropriate write timeout - co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout()))) + co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout()))) if err = co.WriteMsg(m); err != nil { return nil, 0, err } @@ -188,7 +204,69 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro if err == nil && r.Id != m.Id { err = ErrId } - return r, co.rtt, err + rtt = time.Since(t) + return r, rtt, err +} + +func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) { + p, err := m.Pack() + if err != nil { + return nil, 0, err + } + + req, err := http.NewRequest(http.MethodPost, a, bytes.NewReader(p)) + if err != nil { + return nil, 0, err + } + + req.Header.Set("Content-Type", dohMimeType) + req.Header.Set("Accept", dohMimeType) + + hc := http.DefaultClient + if c.HTTPClient != nil { + hc = c.HTTPClient + } + + if ctx != context.Background() && ctx != context.TODO() { + req = req.WithContext(ctx) + } + + t := time.Now() + + resp, err := hc.Do(req) + if err != nil { + return nil, 0, err + } + defer closeHTTPBody(resp.Body) + + if resp.StatusCode != http.StatusOK { + return nil, 0, fmt.Errorf("dns: server returned HTTP %d error: %q", resp.StatusCode, resp.Status) + } + + if ct := resp.Header.Get("Content-Type"); ct != dohMimeType { + return nil, 0, fmt.Errorf("dns: unexpected Content-Type %q; expected %q", ct, dohMimeType) + } + + p, err = ioutil.ReadAll(resp.Body) + if err != nil { + return nil, 0, err + } + + rtt = time.Since(t) + + r = new(Msg) + if err := r.Unpack(p); err != nil { + return r, 0, err + } + + // TODO: TSIG? Is it even supported over DoH? + + return r, rtt, nil +} + +func closeHTTPBody(r io.ReadCloser) error { + io.Copy(ioutil.Discard, io.LimitReader(r, 8<<20)) + return r.Close() } // ReadMsg reads a message from the connection co. @@ -240,7 +318,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) { } p = make([]byte, l) n, err = tcpRead(r, p) - co.rtt = time.Since(co.t) default: if co.UDPSize > MinMsgSize { p = make([]byte, co.UDPSize) @@ -248,7 +325,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) { p = make([]byte, MinMsgSize) } n, err = co.Read(p) - co.rtt = time.Since(co.t) } if err != nil { @@ -361,7 +437,6 @@ func (co *Conn) WriteMsg(m *Msg) (err error) { if err != nil { return err } - co.t = time.Now() if _, err = co.Write(out); err != nil { return err } @@ -493,6 +568,10 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout // context, if present. If there is both a context deadline and a configured // timeout on the client, the earliest of the two takes effect. func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) { + if !c.SingleInflight && c.Net == "https" { + return c.exchangeDOH(ctx, m, a) + } + var timeout time.Duration if deadline, ok := ctx.Deadline(); !ok { timeout = 0 @@ -501,6 +580,7 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, } // not passing the context to the underlying calls, as the API does not support // context. For timeouts you should set up Client.Dialer and call Client.Exchange. + // TODO(tmthrgd): this is a race condition c.Dialer = &net.Dialer{Timeout: timeout} return c.Exchange(m, a) } diff --git a/vendor/github.com/miekg/dns/client_test.go b/vendor/github.com/miekg/dns/client_test.go index cc41983..020e141 100644 --- a/vendor/github.com/miekg/dns/client_test.go +++ b/vendor/github.com/miekg/dns/client_test.go @@ -588,3 +588,25 @@ func TestConcurrentExchanges(t *testing.T) { } } } + +func TestDoHExchange(t *testing.T) { + const addrstr = "https://dns.cloudflare.com/dns-query" + + m := new(Msg) + m.SetQuestion("miek.nl.", TypeSOA) + + cl := &Client{Net: "https"} + + r, _, err := cl.Exchange(m, addrstr) + if err != nil { + t.Fatalf("failed to exchange: %v", err) + } + + if r == nil || r.Rcode != RcodeSuccess { + t.Errorf("failed to get an valid answer\n%v", r) + } + + t.Log(r) + + // TODO: proper tests for this +} diff --git a/vendor/github.com/miekg/dns/clientconfig.go b/vendor/github.com/miekg/dns/clientconfig.go index a606ef6..f13cfa3 100644 --- a/vendor/github.com/miekg/dns/clientconfig.go +++ b/vendor/github.com/miekg/dns/clientconfig.go @@ -91,7 +91,7 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) { n = 1 } c.Timeout = n - case len(s) >= 8 && s[:9] == "attempts:": + case len(s) >= 9 && s[:9] == "attempts:": n, _ := strconv.Atoi(s[9:]) if n < 1 { n = 1 diff --git a/vendor/github.com/miekg/dns/clientconfig_test.go b/vendor/github.com/miekg/dns/clientconfig_test.go index 5c10360..ad5d7d0 100644 --- a/vendor/github.com/miekg/dns/clientconfig_test.go +++ b/vendor/github.com/miekg/dns/clientconfig_test.go @@ -59,7 +59,35 @@ func TestNdots(t *testing.T) { t.Errorf("Ndots not properly parsed: (Expected: %d / Was: %d)", ndotsVariants[data], cc.Ndots) } } +} +func TestClientConfigFromReaderAttempts(t *testing.T) { + testCases := []struct { + data string + expected int + }{ + {data: "options attempts:0", expected: 1}, + {data: "options attempts:1", expected: 1}, + {data: "options attempts:15", expected: 15}, + {data: "options attempts:16", expected: 16}, + {data: "options attempts:-1", expected: 1}, + {data: "options attempt:", expected: 2}, + } + + for _, test := range testCases { + test := test + t.Run(strings.Replace(test.data, ":", " ", -1), func(t *testing.T) { + t.Parallel() + + cc, err := ClientConfigFromReader(strings.NewReader(test.data)) + if err != nil { + t.Errorf("error parsing resolv.conf: %v", err) + } + if cc.Attempts != test.expected { + t.Errorf("A attempts not properly parsed: (Expected: %d / Was: %d)", test.expected, cc.Attempts) + } + }) + } } func TestReadFromFile(t *testing.T) { diff --git a/vendor/github.com/miekg/dns/compress_generate.go b/vendor/github.com/miekg/dns/compress_generate.go index 87fb36f..9a136c4 100644 --- a/vendor/github.com/miekg/dns/compress_generate.go +++ b/vendor/github.com/miekg/dns/compress_generate.go @@ -101,7 +101,8 @@ Names: // compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names - fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n") + fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR, initLen int) int {\n") + fmt.Fprint(b, "currentLen := initLen\n") fmt.Fprint(b, "switch x := r.(type) {\n") for _, name := range domainTypes { o := scope.Lookup(name) @@ -109,7 +110,10 @@ Names: fmt.Fprintf(b, "case *%s:\n", name) for i := 1; i < st.NumFields(); i++ { - out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) } + out := func(s string) { + fmt.Fprintf(b, "currentLen -= len(x.%s) + 1\n", st.Field(i).Name()) + fmt.Fprintf(b, "currentLen += compressionLenHelper(c, x.%s, currentLen)\n", st.Field(i).Name()) + } if _, ok := st.Field(i).Type().(*types.Slice); ok { switch st.Tag(i) { @@ -118,8 +122,12 @@ Names: case `dns:"cdomain-name"`: // For HIP we need to slice over the elements in this slice. fmt.Fprintf(b, `for i := range x.%s { - compressionLenHelper(c, x.%s[i]) - } + currentLen -= len(x.%s[i]) + 1 +} +`, st.Field(i).Name(), st.Field(i).Name()) + fmt.Fprintf(b, `for i := range x.%s { + currentLen += compressionLenHelper(c, x.%s[i], currentLen) +} `, st.Field(i).Name(), st.Field(i).Name()) } continue @@ -133,11 +141,11 @@ Names: } } } - fmt.Fprintln(b, "}\n}\n\n") + fmt.Fprintln(b, "}\nreturn currentLen - initLen\n}\n\n") // compressionLenSearchType - search cdomain-tags types for compressible names. - fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n") + fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {\n") fmt.Fprint(b, "switch x := r.(type) {\n") for _, name := range cdomainTypes { o := scope.Lookup(name) @@ -147,7 +155,7 @@ Names: j := 1 for i := 1; i < st.NumFields(); i++ { out := func(s string, j int) { - fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name()) + fmt.Fprintf(b, "k%d, ok%d, sz%d := compressionLenSearch(c, x.%s)\n", j, j, j, st.Field(i).Name()) } // There are no slice types with names that can be compressed. @@ -160,13 +168,15 @@ Names: } k := "k1" ok := "ok1" + sz := "sz1" for i := 2; i < j; i++ { k += fmt.Sprintf(" + k%d", i) ok += fmt.Sprintf(" && ok%d", i) + sz += fmt.Sprintf(" + sz%d", i) } - fmt.Fprintf(b, "return %s, %s\n", k, ok) + fmt.Fprintf(b, "return %s, %s, %s\n", k, ok, sz) } - fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n") + fmt.Fprintln(b, "}\nreturn 0, false, 0\n}\n\n") // gofmt res, err := format.Source(b.Bytes()) diff --git a/vendor/github.com/miekg/dns/dns.go b/vendor/github.com/miekg/dns/dns.go index 5133eac..e7557f5 100644 --- a/vendor/github.com/miekg/dns/dns.go +++ b/vendor/github.com/miekg/dns/dns.go @@ -55,16 +55,6 @@ func (h *RR_Header) Header() *RR_Header { return h } // Just to implement the RR interface. func (h *RR_Header) copy() RR { return nil } -func (h *RR_Header) copyHeader() *RR_Header { - r := new(RR_Header) - r.Name = h.Name - r.Rrtype = h.Rrtype - r.Class = h.Class - r.Ttl = h.Ttl - r.Rdlength = h.Rdlength - return r -} - func (h *RR_Header) String() string { var s string diff --git a/vendor/github.com/miekg/dns/dns_test.go b/vendor/github.com/miekg/dns/dns_test.go index feface4..3c9d910 100644 --- a/vendor/github.com/miekg/dns/dns_test.go +++ b/vendor/github.com/miekg/dns/dns_test.go @@ -142,152 +142,6 @@ func TestPackNAPTR(t *testing.T) { } } -func TestCompressLength(t *testing.T) { - m := new(Msg) - m.SetQuestion("miek.nl", TypeMX) - ul := m.Len() - m.Compress = true - if ul != m.Len() { - t.Fatalf("should be equal") - } -} - -// Does the predicted length match final packed length? -func TestMsgCompressLength(t *testing.T) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - - name1 := "12345678901234567890123456789012345.12345678.123." - rrA := testRR(name1 + " 3600 IN A 192.0.2.1") - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - tests := []*Msg{ - makeMsg(name1, []RR{rrA}, nil, nil), - makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} - - for _, msg := range tests { - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted < len(buf) { - t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", - msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } - } -} - -func TestMsgLength(t *testing.T) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - return msg - } - - name1 := "12345678901234567890123456789012345.12345678.123." - rrA := testRR(name1 + " 3600 IN A 192.0.2.1") - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - tests := []*Msg{ - makeMsg(name1, []RR{rrA}, nil, nil), - makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} - - for _, msg := range tests { - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted < len(buf) { - t.Errorf("predicted length is wrong: predicted %s (len=%d), actual %d", - msg.Question[0].Name, predicted, len(buf)) - } - } -} - -func TestMsgLength2(t *testing.T) { - // Serialized replies - var testMessages = []string{ - // google.com. IN A? - "064e81800001000b0004000506676f6f676c6503636f6d0000010001c00c00010001000000050004adc22986c00c00010001000000050004adc22987c00c00010001000000050004adc22988c00c00010001000000050004adc22989c00c00010001000000050004adc2298ec00c00010001000000050004adc22980c00c00010001000000050004adc22981c00c00010001000000050004adc22982c00c00010001000000050004adc22983c00c00010001000000050004adc22984c00c00010001000000050004adc22985c00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc0d800010001000000050004d8ef200ac0ea00010001000000050004d8ef220ac0fc00010001000000050004d8ef240ac10e00010001000000050004d8ef260a0000290500000000050000", - // amazon.com. IN A? (reply has no EDNS0 record) - // TODO(miek): this one is off-by-one, need to find out why - //"6de1818000010004000a000806616d617a6f6e03636f6d0000010001c00c000100010000000500044815c2d4c00c000100010000000500044815d7e8c00c00010001000000050004b02062a6c00c00010001000000050004cdfbf236c00c000200010000000500140570646e733408756c747261646e73036f726700c00c000200010000000500150570646e733508756c747261646e7304696e666f00c00c000200010000000500160570646e733608756c747261646e7302636f02756b00c00c00020001000000050014036e7331037033310664796e656374036e657400c00c00020001000000050006036e7332c0cfc00c00020001000000050006036e7333c0cfc00c00020001000000050006036e7334c0cfc00c000200010000000500110570646e733108756c747261646e73c0dac00c000200010000000500080570646e7332c127c00c000200010000000500080570646e7333c06ec0cb00010001000000050004d04e461fc0eb00010001000000050004cc0dfa1fc0fd00010001000000050004d04e471fc10f00010001000000050004cc0dfb1fc12100010001000000050004cc4a6c01c121001c000100000005001020010502f3ff00000000000000000001c13e00010001000000050004cc4a6d01c13e001c0001000000050010261000a1101400000000000000000001", - // yahoo.com. IN A? - "fc2d81800001000300070008057961686f6f03636f6d0000010001c00c00010001000000050004628afd6dc00c00010001000000050004628bb718c00c00010001000000050004cebe242dc00c00020001000000050006036e7336c00cc00c00020001000000050006036e7338c00cc00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7335c00cc07b0001000100000005000444b48310c08d00010001000000050004448eff10c09f00010001000000050004cb54dd35c0b100010001000000050004628a0b9dc0c30001000100000005000477a0f77cc05700010001000000050004ca2bdfaac06900010001000000050004caa568160000290500000000050000", - // microsoft.com. IN A? - "f4368180000100020005000b096d6963726f736f667403636f6d0000010001c00c0001000100000005000440040b25c00c0001000100000005000441373ac9c00c0002000100000005000e036e7331046d736674036e657400c00c00020001000000050006036e7332c04fc00c00020001000000050006036e7333c04fc00c00020001000000050006036e7334c04fc00c00020001000000050006036e7335c04fc04b000100010000000500044137253ec04b001c00010000000500102a010111200500000000000000010001c0650001000100000005000440043badc065001c00010000000500102a010111200600060000000000010001c07700010001000000050004d5c7b435c077001c00010000000500102a010111202000000000000000010001c08900010001000000050004cf2e4bfec089001c00010000000500102404f800200300000000000000010001c09b000100010000000500044137e28cc09b001c00010000000500102a010111200f000100000000000100010000290500000000050000", - // google.com. IN MX? - "724b8180000100050004000b06676f6f676c6503636f6d00000f0001c00c000f000100000005000c000a056173706d78016cc00cc00c000f0001000000050009001404616c7431c02ac00c000f0001000000050009001e04616c7432c02ac00c000f0001000000050009002804616c7433c02ac00c000f0001000000050009003204616c7434c02ac00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7331c00cc02a00010001000000050004adc2421bc02a001c00010000000500102a00145040080c01000000000000001bc04200010001000000050004adc2461bc05700010001000000050004adc2451bc06c000100010000000500044a7d8f1bc081000100010000000500044a7d191bc0ca00010001000000050004d8ef200ac09400010001000000050004d8ef220ac0a600010001000000050004d8ef240ac0b800010001000000050004d8ef260a0000290500000000050000", - // reddit.com. IN A? - "12b98180000100080000000c0672656464697403636f6d0000020001c00c0002000100000005000f046175733204616b616d036e657400c00c000200010000000500070475736534c02dc00c000200010000000500070475737733c02dc00c000200010000000500070475737735c02dc00c00020001000000050008056173696131c02dc00c00020001000000050008056173696139c02dc00c00020001000000050008056e73312d31c02dc00c0002000100000005000a076e73312d313935c02dc02800010001000000050004c30a242ec04300010001000000050004451f1d39c05600010001000000050004451f3bc7c0690001000100000005000460073240c07c000100010000000500046007fb81c090000100010000000500047c283484c090001c00010000000500102a0226f0006700000000000000000064c0a400010001000000050004c16c5b01c0a4001c000100000005001026001401000200000000000000000001c0b800010001000000050004c16c5bc3c0b8001c0001000000050010260014010002000000000000000000c30000290500000000050000", - } - - for i, hexData := range testMessages { - // we won't fail the decoding of the hex - input, _ := hex.DecodeString(hexData) - - m := new(Msg) - m.Unpack(input) - m.Compress = true - lenComp := m.Len() - b, _ := m.Pack() - pacComp := len(b) - m.Compress = false - lenUnComp := m.Len() - b, _ = m.Pack() - pacUnComp := len(b) - if pacComp+1 != lenComp { - t.Errorf("msg.Len(compressed)=%d actual=%d for test %d", lenComp, pacComp, i) - } - if pacUnComp+1 != lenUnComp { - t.Errorf("msg.Len(uncompressed)=%d actual=%d for test %d", lenUnComp, pacUnComp, i) - } - } -} - -func TestMsgLengthCompressionMalformed(t *testing.T) { - // SOA with empty hostmaster, which is illegal - soa := &SOA{Hdr: RR_Header{Name: ".", Rrtype: TypeSOA, Class: ClassINET, Ttl: 12345}, - Ns: ".", - Mbox: "", - Serial: 0, - Refresh: 28800, - Retry: 7200, - Expire: 604800, - Minttl: 60} - m := new(Msg) - m.Compress = true - m.Ns = []RR{soa} - m.Len() // Should not crash. -} - -func TestMsgCompressLength2(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion(Fqdn("bliep."), TypeANY) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "blaat.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: "foo.bar."}) - msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: "foo.bar.", Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, A: net.IP{0xac, 0x11, 0x0, 0x3}}) - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted != len(buf) { - t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", - msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } -} - func TestToRFC3597(t *testing.T) { a := testRR("miek.nl. IN A 10.0.1.1") x := new(RFC3597) diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go index ac9fdd4..7e6bac4 100644 --- a/vendor/github.com/miekg/dns/dnssec.go +++ b/vendor/github.com/miekg/dns/dnssec.go @@ -73,6 +73,7 @@ var StringToAlgorithm = reverseInt8(AlgorithmToString) // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's. var AlgorithmToHash = map[uint8]crypto.Hash{ RSAMD5: crypto.MD5, // Deprecated in RFC 6725 + DSA: crypto.SHA1, RSASHA1: crypto.SHA1, RSASHA1NSEC3SHA1: crypto.SHA1, RSASHA256: crypto.SHA256, @@ -239,7 +240,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS { // ToCDNSKEY converts a DNSKEY record to a CDNSKEY record. func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { c := &CDNSKEY{DNSKEY: *k} - c.Hdr = *k.Hdr.copyHeader() + c.Hdr = k.Hdr c.Hdr.Rrtype = TypeCDNSKEY return c } @@ -247,7 +248,7 @@ func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { // ToCDS converts a DS record to a CDS record. func (d *DS) ToCDS() *CDS { c := &CDS{DS: *d} - c.Hdr = *d.Hdr.copyHeader() + c.Hdr = d.Hdr c.Hdr.Rrtype = TypeCDS return c } @@ -541,20 +542,20 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) keyoff = 3 } + if explen > 4 { + // Larger exponent than supported by the crypto package. + return nil + } pubkey := new(rsa.PublicKey) pubkey.N = big.NewInt(0) - shift := uint64((explen - 1) * 8) expo := uint64(0) - for i := int(explen - 1); i > 0; i-- { - expo += uint64(keybuf[keyoff+i]) << shift - shift -= 8 + for i := 0; i < int(explen); i++ { + expo <<= 8 + expo |= uint64(keybuf[keyoff+i]) } - // Remainder - expo += uint64(keybuf[keyoff]) - if expo > (2<<31)+1 { - // Larger expo than supported. - // println("dns: F5 primes (or larger) are not supported") + if expo > 1<<31-1 { + // Larger exponent than supported by the crypto package. return nil } pubkey.E = int(expo) diff --git a/vendor/github.com/miekg/dns/dnssec_test.go b/vendor/github.com/miekg/dns/dnssec_test.go index 7cf7c41..2dea4e5 100644 --- a/vendor/github.com/miekg/dns/dnssec_test.go +++ b/vendor/github.com/miekg/dns/dnssec_test.go @@ -839,3 +839,22 @@ func TestInvalidRRSet(t *testing.T) { t.Fatal("Verification did not return ErrRRset with inconsistent records") } } + +// Issue #688 - RSA exponent unpacked in reverse +func TestRsaExponentUnpack(t *testing.T) { + zskRrDnskey, _ := NewRR("isc.org. 7200 IN DNSKEY 256 3 5 AwEAAcdkaRUlsRD4gcF63PpPJJ1E6kOIb3yn/UHptVsPEQtEbgJ2y20O eix4unpwoQkz+bIAd2rrOU/95wgV530x0/qqKwBLWoGkxdcnNcvVT4hl 3SOTZy1VjwkAfyayHPU8VisXqJGbB3KWevBZlb6AtrXzFu8AHuBeeAAe /fOgreCh") + kskRrDnskey, _ := NewRR("isc.org. 7200 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGr hhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+ u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy3 47cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQz Bkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyL KOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bB yBNsO70aEFTd") + kskRrRrsig, _ := NewRR("isc.org. 7200 IN RRSIG DNSKEY 5 2 7200 20180627230244 20180528230244 12892 isc.org. ebKBlhYi1hPGTdPg6zSwvprOIkoFMs+WIhMSjoYW6/K5CS9lDDFdK4cu TgXJRT3etrltTuJiFe2HRpp+7t5cKLy+CeJZVzqrCz200MoHiFuLI9yI DJQGaS5YYCiFbw5+jUGU6aUhZ7Y5/YufeqATkRZzdrKwgK+zri8LPw9T WLoVJPAOW7GR0dgxl9WKmO7Fzi9P8BZR3NuwLV7329X94j+4zyswaw7q e5vif0ybzFveODLsEi/E0a2rTXc4QzzyM0fSVxRkVQyQ7ifIPP4ohnnT d5qpPUbE8xxBzTdWR/TaKADC5aCFkppG9lVAq5CPfClii2949X5RYzy1 rxhuSA==") + zskRrRrsig, _ := NewRR("isc.org. 7200 IN RRSIG DNSKEY 5 2 7200 20180627230244 20180528230244 19923 isc.org. RgCfzUeq4RJPGoe9RRB6cWf6d/Du+tHK5SxI5QL1waA3O5qVtQKFkY1C dq/yyVjwzfjD9F62TObujOaktv8X80ZMcNPmgHbvK1xOqelMBWv5hxj3 xRe+QQObLZ5NPfHFsphQKXvwgO5Sjk8py2B2iCr3BHCZ8S38oIfuSrQx sn8=") + + zsk, ksk := zskRrDnskey.(*DNSKEY), kskRrDnskey.(*DNSKEY) + zskSig, kskSig := zskRrRrsig.(*RRSIG), kskRrRrsig.(*RRSIG) + + if e := zskSig.Verify(zsk, []RR{zsk, ksk}); e != nil { + t.Fatalf("cannot verify RRSIG with keytag [%d]. Cause [%s]", zsk.KeyTag(), e.Error()) + } + + if e := kskSig.Verify(ksk, []RR{zsk, ksk}); e != nil { + t.Fatalf("cannot verify RRSIG with keytag [%d]. Cause [%s]", ksk.KeyTag(), e.Error()) + } +} diff --git a/vendor/github.com/miekg/dns/doc.go b/vendor/github.com/miekg/dns/doc.go index 1d81147..0389d72 100644 --- a/vendor/github.com/miekg/dns/doc.go +++ b/vendor/github.com/miekg/dns/doc.go @@ -73,11 +73,11 @@ and port to use for the connection: Port: 12345, Zone: "", } - d := net.Dialer{ + c.Dialer := &net.Dialer{ Timeout: 200 * time.Millisecond, LocalAddr: &laddr, } - in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53") + in, rtt, err := c.Exchange(m1, "8.8.8.8:53") If these "advanced" features are not needed, a simple UDP query can be sent, with: diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go index 6f9d2ea..55059eb 100644 --- a/vendor/github.com/miekg/dns/edns.go +++ b/vendor/github.com/miekg/dns/edns.go @@ -102,12 +102,15 @@ func (rr *OPT) SetVersion(v uint8) { // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL). func (rr *OPT) ExtendedRcode() int { - return int((rr.Hdr.Ttl & 0xFF000000) >> 24) + return int((rr.Hdr.Ttl&0xFF000000)>>24) + 15 } // SetExtendedRcode sets the EDNS extended RCODE field. func (rr *OPT) SetExtendedRcode(v uint8) { - rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24) + if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have! + return + } + rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v-15) << 24) } // UDPSize returns the UDP buffer size. diff --git a/vendor/github.com/miekg/dns/leak_test.go b/vendor/github.com/miekg/dns/leak_test.go index af37011..ff83ac7 100644 --- a/vendor/github.com/miekg/dns/leak_test.go +++ b/vendor/github.com/miekg/dns/leak_test.go @@ -29,6 +29,7 @@ func interestingGoroutines() (gs []string) { strings.Contains(stack, "closeWriteAndWait") || strings.Contains(stack, "testing.Main(") || strings.Contains(stack, "testing.(*T).Run(") || + strings.Contains(stack, "created by net/http.(*http2Transport).newClientConn") || // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) strings.Contains(stack, "runtime.goexit") || strings.Contains(stack, "created by runtime.gc") || diff --git a/vendor/github.com/miekg/dns/length_test.go b/vendor/github.com/miekg/dns/length_test.go new file mode 100644 index 0000000..66521a5 --- /dev/null +++ b/vendor/github.com/miekg/dns/length_test.go @@ -0,0 +1,371 @@ +package dns + +import ( + "encoding/hex" + "fmt" + "net" + "reflect" + "strings" + "testing" +) + +func TestCompressLength(t *testing.T) { + m := new(Msg) + m.SetQuestion("miek.nl", TypeMX) + ul := m.Len() + m.Compress = true + if ul != m.Len() { + t.Fatalf("should be equal") + } +} + +// Does the predicted length match final packed length? +func TestMsgCompressLength(t *testing.T) { + makeMsg := func(question string, ans, ns, e []RR) *Msg { + msg := new(Msg) + msg.SetQuestion(Fqdn(question), TypeANY) + msg.Answer = append(msg.Answer, ans...) + msg.Ns = append(msg.Ns, ns...) + msg.Extra = append(msg.Extra, e...) + msg.Compress = true + return msg + } + + name1 := "12345678901234567890123456789012345.12345678.123." + rrA := testRR(name1 + " 3600 IN A 192.0.2.1") + rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) + tests := []*Msg{ + makeMsg(name1, []RR{rrA}, nil, nil), + makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} + + for _, msg := range tests { + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted < len(buf) { + t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", + msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) + } + } +} + +func TestMsgLength(t *testing.T) { + makeMsg := func(question string, ans, ns, e []RR) *Msg { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion(Fqdn(question), TypeANY) + msg.Answer = append(msg.Answer, ans...) + msg.Ns = append(msg.Ns, ns...) + msg.Extra = append(msg.Extra, e...) + return msg + } + + name1 := "12345678901234567890123456789012345.12345678.123." + rrA := testRR(name1 + " 3600 IN A 192.0.2.1") + rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) + tests := []*Msg{ + makeMsg(name1, []RR{rrA}, nil, nil), + makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} + + for _, msg := range tests { + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted < len(buf) { + t.Errorf("predicted length is wrong: predicted %s (len=%d), actual %d", + msg.Question[0].Name, predicted, len(buf)) + } + } +} + +func TestCompressionLenHelper(t *testing.T) { + c := make(map[string]int) + compressionLenHelper(c, "example.com", 12) + if c["example.com"] != 12 { + t.Errorf("bad %d", c["example.com"]) + } + if c["com"] != 20 { + t.Errorf("bad %d", c["com"]) + } + + // Test boundaries + c = make(map[string]int) + // foo label starts at 16379 + // com label starts at 16384 + compressionLenHelper(c, "foo.com", 16379) + if c["foo.com"] != 16379 { + t.Errorf("bad %d", c["foo.com"]) + } + // com label is accessible + if c["com"] != 16383 { + t.Errorf("bad %d", c["com"]) + } + + c = make(map[string]int) + // foo label starts at 16379 + // com label starts at 16385 => outside range + compressionLenHelper(c, "foo.com", 16380) + if c["foo.com"] != 16380 { + t.Errorf("bad %d", c["foo.com"]) + } + // com label is NOT accessible + if c["com"] != 0 { + t.Errorf("bad %d", c["com"]) + } + + c = make(map[string]int) + compressionLenHelper(c, "example.com", 16375) + if c["example.com"] != 16375 { + t.Errorf("bad %d", c["example.com"]) + } + // com starts AFTER 16384 + if c["com"] != 16383 { + t.Errorf("bad %d", c["com"]) + } + + c = make(map[string]int) + compressionLenHelper(c, "example.com", 16376) + if c["example.com"] != 16376 { + t.Errorf("bad %d", c["example.com"]) + } + // com starts AFTER 16384 + if c["com"] != 0 { + t.Errorf("bad %d", c["com"]) + } +} + +func TestCompressionLenSearch(t *testing.T) { + c := make(map[string]int) + compressed, ok, fullSize := compressionLenSearch(c, "a.b.org.") + if compressed != 0 || ok || fullSize != 14 { + panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) + } + c["org."] = 3 + compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") + if compressed != 4 || !ok || fullSize != 8 { + panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) + } + c["b.org."] = 5 + compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") + if compressed != 6 || !ok || fullSize != 4 { + panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) + } + // Not found long compression + c["x.b.org."] = 5 + compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") + if compressed != 6 || !ok || fullSize != 4 { + panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) + } + // Found long compression + c["a.b.org."] = 5 + compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") + if compressed != 8 || !ok || fullSize != 0 { + panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) + } +} + +func TestMsgLength2(t *testing.T) { + // Serialized replies + var testMessages = []string{ + // google.com. IN A? + "064e81800001000b0004000506676f6f676c6503636f6d0000010001c00c00010001000000050004adc22986c00c00010001000000050004adc22987c00c00010001000000050004adc22988c00c00010001000000050004adc22989c00c00010001000000050004adc2298ec00c00010001000000050004adc22980c00c00010001000000050004adc22981c00c00010001000000050004adc22982c00c00010001000000050004adc22983c00c00010001000000050004adc22984c00c00010001000000050004adc22985c00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc0d800010001000000050004d8ef200ac0ea00010001000000050004d8ef220ac0fc00010001000000050004d8ef240ac10e00010001000000050004d8ef260a0000290500000000050000", + // amazon.com. IN A? (reply has no EDNS0 record) + // TODO(miek): this one is off-by-one, need to find out why + //"6de1818000010004000a000806616d617a6f6e03636f6d0000010001c00c000100010000000500044815c2d4c00c000100010000000500044815d7e8c00c00010001000000050004b02062a6c00c00010001000000050004cdfbf236c00c000200010000000500140570646e733408756c747261646e73036f726700c00c000200010000000500150570646e733508756c747261646e7304696e666f00c00c000200010000000500160570646e733608756c747261646e7302636f02756b00c00c00020001000000050014036e7331037033310664796e656374036e657400c00c00020001000000050006036e7332c0cfc00c00020001000000050006036e7333c0cfc00c00020001000000050006036e7334c0cfc00c000200010000000500110570646e733108756c747261646e73c0dac00c000200010000000500080570646e7332c127c00c000200010000000500080570646e7333c06ec0cb00010001000000050004d04e461fc0eb00010001000000050004cc0dfa1fc0fd00010001000000050004d04e471fc10f00010001000000050004cc0dfb1fc12100010001000000050004cc4a6c01c121001c000100000005001020010502f3ff00000000000000000001c13e00010001000000050004cc4a6d01c13e001c0001000000050010261000a1101400000000000000000001", + // yahoo.com. IN A? + "fc2d81800001000300070008057961686f6f03636f6d0000010001c00c00010001000000050004628afd6dc00c00010001000000050004628bb718c00c00010001000000050004cebe242dc00c00020001000000050006036e7336c00cc00c00020001000000050006036e7338c00cc00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7335c00cc07b0001000100000005000444b48310c08d00010001000000050004448eff10c09f00010001000000050004cb54dd35c0b100010001000000050004628a0b9dc0c30001000100000005000477a0f77cc05700010001000000050004ca2bdfaac06900010001000000050004caa568160000290500000000050000", + // microsoft.com. IN A? + "f4368180000100020005000b096d6963726f736f667403636f6d0000010001c00c0001000100000005000440040b25c00c0001000100000005000441373ac9c00c0002000100000005000e036e7331046d736674036e657400c00c00020001000000050006036e7332c04fc00c00020001000000050006036e7333c04fc00c00020001000000050006036e7334c04fc00c00020001000000050006036e7335c04fc04b000100010000000500044137253ec04b001c00010000000500102a010111200500000000000000010001c0650001000100000005000440043badc065001c00010000000500102a010111200600060000000000010001c07700010001000000050004d5c7b435c077001c00010000000500102a010111202000000000000000010001c08900010001000000050004cf2e4bfec089001c00010000000500102404f800200300000000000000010001c09b000100010000000500044137e28cc09b001c00010000000500102a010111200f000100000000000100010000290500000000050000", + // google.com. IN MX? + "724b8180000100050004000b06676f6f676c6503636f6d00000f0001c00c000f000100000005000c000a056173706d78016cc00cc00c000f0001000000050009001404616c7431c02ac00c000f0001000000050009001e04616c7432c02ac00c000f0001000000050009002804616c7433c02ac00c000f0001000000050009003204616c7434c02ac00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7331c00cc02a00010001000000050004adc2421bc02a001c00010000000500102a00145040080c01000000000000001bc04200010001000000050004adc2461bc05700010001000000050004adc2451bc06c000100010000000500044a7d8f1bc081000100010000000500044a7d191bc0ca00010001000000050004d8ef200ac09400010001000000050004d8ef220ac0a600010001000000050004d8ef240ac0b800010001000000050004d8ef260a0000290500000000050000", + // reddit.com. IN A? + "12b98180000100080000000c0672656464697403636f6d0000020001c00c0002000100000005000f046175733204616b616d036e657400c00c000200010000000500070475736534c02dc00c000200010000000500070475737733c02dc00c000200010000000500070475737735c02dc00c00020001000000050008056173696131c02dc00c00020001000000050008056173696139c02dc00c00020001000000050008056e73312d31c02dc00c0002000100000005000a076e73312d313935c02dc02800010001000000050004c30a242ec04300010001000000050004451f1d39c05600010001000000050004451f3bc7c0690001000100000005000460073240c07c000100010000000500046007fb81c090000100010000000500047c283484c090001c00010000000500102a0226f0006700000000000000000064c0a400010001000000050004c16c5b01c0a4001c000100000005001026001401000200000000000000000001c0b800010001000000050004c16c5bc3c0b8001c0001000000050010260014010002000000000000000000c30000290500000000050000", + } + + for i, hexData := range testMessages { + // we won't fail the decoding of the hex + input, _ := hex.DecodeString(hexData) + + m := new(Msg) + m.Unpack(input) + m.Compress = true + lenComp := m.Len() + b, _ := m.Pack() + pacComp := len(b) + m.Compress = false + lenUnComp := m.Len() + b, _ = m.Pack() + pacUnComp := len(b) + if pacComp+1 != lenComp { + t.Errorf("msg.Len(compressed)=%d actual=%d for test %d", lenComp, pacComp, i) + } + if pacUnComp+1 != lenUnComp { + t.Errorf("msg.Len(uncompressed)=%d actual=%d for test %d", lenUnComp, pacUnComp, i) + } + } +} + +func TestMsgLengthCompressionMalformed(t *testing.T) { + // SOA with empty hostmaster, which is illegal + soa := &SOA{Hdr: RR_Header{Name: ".", Rrtype: TypeSOA, Class: ClassINET, Ttl: 12345}, + Ns: ".", + Mbox: "", + Serial: 0, + Refresh: 28800, + Retry: 7200, + Expire: 604800, + Minttl: 60} + m := new(Msg) + m.Compress = true + m.Ns = []RR{soa} + m.Len() // Should not crash. +} + +func TestMsgCompressLength2(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion(Fqdn("bliep."), TypeANY) + msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "blaat.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: "foo.bar."}) + msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: "foo.bar.", Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, A: net.IP{0xac, 0x11, 0x0, 0x3}}) + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted != len(buf) { + t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", + msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) + } +} + +func TestMsgCompressLengthLargeRecords(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion("my.service.acme.", TypeSRV) + j := 1 + for i := 0; i < 250; i++ { + target := fmt.Sprintf("host-redis-1-%d.test.acme.com.node.dc1.consul.", i) + msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) + msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: 1, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", j, i)}) + } + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted != len(buf) { + t.Fatalf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) + } +} + +func TestCompareCompressionMapsForANY(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion("a.service.acme.", TypeANY) + // Be sure to have more than 14bits + for i := 0; i < 2000; i++ { + target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i) + msg.Answer = append(msg.Answer, &AAAA{Hdr: RR_Header{Name: target, Rrtype: TypeAAAA, Class: ClassINET, Ttl: 0x3c}, AAAA: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, byte(i / 255), byte(i % 255)}}) + msg.Answer = append(msg.Answer, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}}) + if msg.Len() > 16384 { + break + } + } + for labelSize := 0; labelSize < 63; labelSize++ { + msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeANY) + + compressionFake := make(map[string]int) + lenFake := compressedLenWithCompressionMap(msg, compressionFake) + + compressionReal := make(map[string]int) + buf, err := msg.packBufferWithCompressionMap(nil, compressionReal) + if err != nil { + t.Fatal(err) + } + if lenFake != len(buf) { + t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf)) + } + if !reflect.DeepEqual(compressionFake, compressionReal) { + t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n*** Real:= %v\n\n***Fake:= %v", labelSize, compressionReal, compressionFake) + } + } +} + +func TestCompareCompressionMapsForSRV(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion("a.service.acme.", TypeSRV) + // Be sure to have more than 14bits + for i := 0; i < 2000; i++ { + target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i) + msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: ClassINET, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) + msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}}) + if msg.Len() > 16384 { + break + } + } + for labelSize := 0; labelSize < 63; labelSize++ { + msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeAAAA) + + compressionFake := make(map[string]int) + lenFake := compressedLenWithCompressionMap(msg, compressionFake) + + compressionReal := make(map[string]int) + buf, err := msg.packBufferWithCompressionMap(nil, compressionReal) + if err != nil { + t.Fatal(err) + } + if lenFake != len(buf) { + t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf)) + } + if !reflect.DeepEqual(compressionFake, compressionReal) { + t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n*** Real:= %v\n\n***Fake:= %v", labelSize, compressionReal, compressionFake) + } + } +} + +func TestMsgCompressLengthLargeRecordsWithPaddingPermutation(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion("my.service.acme.", TypeSRV) + + for i := 0; i < 250; i++ { + target := fmt.Sprintf("host-redis-x-%d.test.acme.com.node.dc1.consul.", i) + msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) + msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.x.%d.", i)}) + } + for labelSize := 1; labelSize < 63; labelSize++ { + msg.SetQuestion(fmt.Sprintf("my.%s.service.acme.", strings.Repeat("x", labelSize)), TypeSRV) + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted != len(buf) { + t.Fatalf("padding= %d ; predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", labelSize, msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) + } + } +} + +func TestMsgCompressLengthLargeRecordsAllValues(t *testing.T) { + msg := new(Msg) + msg.Compress = true + msg.SetQuestion("redis.service.consul.", TypeSRV) + for i := 0; i < 900; i++ { + target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256) + msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) + msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)}) + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted != len(buf) { + t.Fatalf("predicted compressed length is wrong for %d records: predicted %s (len=%d) %d, actual %d", i, msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) + } + } +} diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go index 975dde7..dcd3b6a 100644 --- a/vendor/github.com/miekg/dns/msg.go +++ b/vendor/github.com/miekg/dns/msg.go @@ -595,6 +595,13 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) { if err != nil { return nil, len(msg), err } + + return UnpackRRWithHeader(h, msg, off) +} + +// UnpackRRWithHeader unpacks the record type specific payload given an existing +// RR_Header. +func UnpackRRWithHeader(h RR_Header, msg []byte, off int) (rr RR, off1 int, err error) { end := off + int(h.Rdlength) if fn, known := typeToUnpack[h.Rrtype]; !known { @@ -684,18 +691,20 @@ func (dns *Msg) Pack() (msg []byte, err error) { return dns.PackBuffer(nil) } -// PackBuffer packs a Msg, using the given buffer buf. If buf is too small -// a new buffer is allocated. +// PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated. func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) { - // We use a similar function in tsig.go's stripTsig. - var ( - dh Header - compression map[string]int - ) - + var compression map[string]int if dns.Compress { - compression = make(map[string]int) // Compression pointer mappings + compression = make(map[string]int) // Compression pointer mappings. } + return dns.packBufferWithCompressionMap(buf, compression) +} + +// packBufferWithCompressionMap packs a Msg, using the given buffer buf. +func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]int) (msg []byte, err error) { + // We use a similar function in tsig.go's stripTsig. + + var dh Header if dns.Rcode < 0 || dns.Rcode > 0xFFF { return nil, ErrRcode @@ -707,12 +716,11 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) { return nil, ErrExtendedRcode } opt.SetExtendedRcode(uint8(dns.Rcode >> 4)) - dns.Rcode &= 0xF } // Convert convenient Msg into wire-like Header. dh.Id = dns.Id - dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode) + dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF) if dns.Response { dh.Bits |= _QR } @@ -915,94 +923,138 @@ func (dns *Msg) String() string { // than packing it, measuring the size and discarding the buffer. func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) } +func compressedLenWithCompressionMap(dns *Msg, compression map[string]int) int { + l := 12 // Message header is always 12 bytes + for _, r := range dns.Question { + compressionLenHelper(compression, r.Name, l) + l += r.len() + } + l += compressionLenSlice(l, compression, dns.Answer) + l += compressionLenSlice(l, compression, dns.Ns) + l += compressionLenSlice(l, compression, dns.Extra) + return l +} + // compressedLen returns the message length when in compressed wire format // when compress is true, otherwise the uncompressed length is returned. func compressedLen(dns *Msg, compress bool) int { // We always return one more than needed. - l := 12 // Message header is always 12 bytes if compress { compression := map[string]int{} - for _, r := range dns.Question { + return compressedLenWithCompressionMap(dns, compression) + } + l := 12 // Message header is always 12 bytes + + for _, r := range dns.Question { + l += r.len() + } + for _, r := range dns.Answer { + if r != nil { l += r.len() - compressionLenHelper(compression, r.Name) - } - l += compressionLenSlice(compression, dns.Answer) - l += compressionLenSlice(compression, dns.Ns) - l += compressionLenSlice(compression, dns.Extra) - } else { - for _, r := range dns.Question { - l += r.len() - } - for _, r := range dns.Answer { - if r != nil { - l += r.len() - } - } - for _, r := range dns.Ns { - if r != nil { - l += r.len() - } - } - for _, r := range dns.Extra { - if r != nil { - l += r.len() - } } } + for _, r := range dns.Ns { + if r != nil { + l += r.len() + } + } + for _, r := range dns.Extra { + if r != nil { + l += r.len() + } + } + return l } -func compressionLenSlice(c map[string]int, rs []RR) int { - var l int +func compressionLenSlice(lenp int, c map[string]int, rs []RR) int { + initLen := lenp for _, r := range rs { if r == nil { continue } - l += r.len() - k, ok := compressionLenSearch(c, r.Header().Name) + // TmpLen is to track len of record at 14bits boudaries + tmpLen := lenp + + x := r.len() + // track this length, and the global length in len, while taking compression into account for both. + k, ok, _ := compressionLenSearch(c, r.Header().Name) if ok { - l += 1 - k + // Size of x is reduced by k, but we add 1 since k includes the '.' and label descriptor take 2 bytes + // so, basically x:= x - k - 1 + 2 + x += 1 - k } - compressionLenHelper(c, r.Header().Name) - k, ok = compressionLenSearchType(c, r) + + tmpLen += compressionLenHelper(c, r.Header().Name, tmpLen) + k, ok, _ = compressionLenSearchType(c, r) if ok { - l += 1 - k + x += 1 - k } - compressionLenHelperType(c, r) + lenp += x + tmpLen = lenp + tmpLen += compressionLenHelperType(c, r, tmpLen) + } - return l + return lenp - initLen } -// Put the parts of the name in the compression map. -func compressionLenHelper(c map[string]int, s string) { +// Put the parts of the name in the compression map, return the size in bytes added in payload +func compressionLenHelper(c map[string]int, s string, currentLen int) int { + if currentLen > maxCompressionOffset { + // We won't be able to add any label that could be re-used later anyway + return 0 + } + if _, ok := c[s]; ok { + return 0 + } + initLen := currentLen pref := "" + prev := s lbs := Split(s) - for j := len(lbs) - 1; j >= 0; j-- { + for j := 0; j < len(lbs); j++ { pref = s[lbs[j]:] + currentLen += len(prev) - len(pref) + prev = pref if _, ok := c[pref]; !ok { - c[pref] = len(pref) + // If first byte label is within the first 14bits, it might be re-used later + if currentLen < maxCompressionOffset { + c[pref] = currentLen + } + } else { + added := currentLen - initLen + if j > 0 { + // We added a new PTR + added += 2 + } + return added } } + return currentLen - initLen } // Look for each part in the compression map and returns its length, // keep on searching so we get the longest match. -func compressionLenSearch(c map[string]int, s string) (int, bool) { +// Will return the size of compression found, whether a match has been +// found and the size of record if added in payload +func compressionLenSearch(c map[string]int, s string) (int, bool, int) { off := 0 end := false if s == "" { // don't bork on bogus data - return 0, false + return 0, false, 0 } + fullSize := 0 for { if _, ok := c[s[off:]]; ok { - return len(s[off:]), true + return len(s[off:]), true, fullSize + off } if end { break } + // Each label descriptor takes 2 bytes, add it + fullSize += 2 off, end = NextLabel(s, off) } - return 0, false + return 0, false, fullSize + len(s) } // Copy returns a new RR which is a deep-copy of r. diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go index 946d5ac..4a6e878 100644 --- a/vendor/github.com/miekg/dns/msg_helpers.go +++ b/vendor/github.com/miekg/dns/msg_helpers.go @@ -141,20 +141,24 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b return msg[:lenrd], nil } +var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding) + func fromBase32(s []byte) (buf []byte, err error) { for i, b := range s { if b >= 'a' && b <= 'z' { s[i] = b - 32 } } - buflen := base32.HexEncoding.DecodedLen(len(s)) + buflen := base32HexNoPadEncoding.DecodedLen(len(s)) buf = make([]byte, buflen) - n, err := base32.HexEncoding.Decode(buf, s) + n, err := base32HexNoPadEncoding.Decode(buf, s) buf = buf[:n] return } -func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) } +func toBase32(b []byte) string { + return base32HexNoPadEncoding.EncodeToString(b) +} func fromBase64(s []byte) (buf []byte, err error) { buflen := base64.StdEncoding.DecodedLen(len(s)) diff --git a/vendor/github.com/miekg/dns/msg_test.go b/vendor/github.com/miekg/dns/msg_test.go index 2dbef62..afbe6d8 100644 --- a/vendor/github.com/miekg/dns/msg_test.go +++ b/vendor/github.com/miekg/dns/msg_test.go @@ -26,6 +26,28 @@ var ( }) ) +func TestPackNoSideEffect(t *testing.T) { + m := new(Msg) + m.SetQuestion(Fqdn("example.com."), TypeNS) + + a := new(Msg) + o := &OPT{ + Hdr: RR_Header{ + Name: ".", + Rrtype: TypeOPT, + }, + } + o.SetUDPSize(DefaultMsgSize) + + a.Extra = append(a.Extra, o) + a.SetRcode(m, RcodeBadVers) + + a.Pack() + if a.Rcode != RcodeBadVers { + t.Errorf("after pack: Rcode is expected to be BADVERS") + } +} + func TestUnpackDomainName(t *testing.T) { var cases = []struct { label string diff --git a/vendor/github.com/miekg/dns/nsecx_test.go b/vendor/github.com/miekg/dns/nsecx_test.go index f8edd6d..74ebda3 100644 --- a/vendor/github.com/miekg/dns/nsecx_test.go +++ b/vendor/github.com/miekg/dns/nsecx_test.go @@ -131,3 +131,11 @@ func TestNsec3(t *testing.T) { } } } + +func TestNsec3EmptySalt(t *testing.T) { + rr, _ := NewRR("CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A NS SOA RRSIG DNSKEY NSEC3PARAM") + + if !rr.(*NSEC3).Match("com.") { + t.Fatalf("expected record to match com. label") + } +} diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go index 6b08e6e..41989e7 100644 --- a/vendor/github.com/miekg/dns/privaterr.go +++ b/vendor/github.com/miekg/dns/privaterr.go @@ -56,8 +56,7 @@ func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() } func (r *PrivateRR) copy() RR { // make new RR like this: rr := mkPrivateRR(r.Hdr.Rrtype) - newh := r.Hdr.copyHeader() - rr.Hdr = *newh + rr.Hdr = r.Hdr err := r.Data.Copy(rr.Data) if err != nil { diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go index f4ccc84..fb6f95d 100644 --- a/vendor/github.com/miekg/dns/scan_rr.go +++ b/vendor/github.com/miekg/dns/scan_rr.go @@ -1255,8 +1255,10 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad NSEC3 Salt", l}, "" } - rr.SaltLength = uint8(len(l.token)) / 2 - rr.Salt = l.token + if l.token != "-" { + rr.SaltLength = uint8(len(l.token)) / 2 + rr.Salt = l.token + } <-c l = <-c @@ -1321,8 +1323,10 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin rr.Iterations = uint16(i) <-c l = <-c - rr.SaltLength = uint8(len(l.token)) - rr.Salt = l.token + if l.token != "-" { + rr.SaltLength = uint8(len(l.token)) + rr.Salt = l.token + } return rr, nil, "" } diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go index b79abad..2d98f14 100644 --- a/vendor/github.com/miekg/dns/server.go +++ b/vendor/github.com/miekg/dns/server.go @@ -9,12 +9,19 @@ import ( "io" "net" "sync" + "sync/atomic" "time" ) -// Maximum number of TCP queries before we close the socket. +// Default maximum number of TCP queries before we close the socket. const maxTCPQueries = 128 +// Interval for stop worker if no load +const idleWorkerTimeout = 10 * time.Second + +// Maximum number of workers +const maxWorkersCount = 10000 + // Handler is implemented by any value that implements ServeDNS. type Handler interface { ServeDNS(w ResponseWriter, r *Msg) @@ -43,6 +50,7 @@ type ResponseWriter interface { } type response struct { + msg []byte hijacked bool // connection has been hijacked by handler tsigStatus error tsigTimersOnly bool @@ -51,7 +59,6 @@ type response struct { udp *net.UDPConn // i/o connection if UDP was used tcp net.Conn // i/o connection if TCP was used udpSession *SessionUDP // oob data to get egress interface right - remoteAddr net.Addr // address of the client writer Writer // writer to output the raw DNS bits } @@ -296,12 +303,63 @@ type Server struct { DecorateReader DecorateReader // DecorateWriter is optional, allows customization of the process that writes raw DNS messages. DecorateWriter DecorateWriter + // Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1). + MaxTCPQueries int + // UDP packet or TCP connection queue + queue chan *response + // Workers count + workersCount int32 // Shutdown handling lock sync.RWMutex started bool } +func (srv *Server) worker(w *response) { + srv.serve(w) + + for { + count := atomic.LoadInt32(&srv.workersCount) + if count > maxWorkersCount { + return + } + if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) { + break + } + } + + defer atomic.AddInt32(&srv.workersCount, -1) + + inUse := false + timeout := time.NewTimer(idleWorkerTimeout) + defer timeout.Stop() +LOOP: + for { + select { + case w, ok := <-srv.queue: + if !ok { + break LOOP + } + inUse = true + srv.serve(w) + case <-timeout.C: + if !inUse { + break LOOP + } + inUse = false + timeout.Reset(idleWorkerTimeout) + } + } +} + +func (srv *Server) spawnWorker(w *response) { + select { + case srv.queue <- w: + default: + go srv.worker(w) + } +} + // ListenAndServe starts a nameserver on the configured address in *Server. func (srv *Server) ListenAndServe() error { srv.lock.Lock() @@ -309,6 +367,7 @@ func (srv *Server) ListenAndServe() error { if srv.started { return &Error{err: "server already started"} } + addr := srv.Addr if addr == "" { addr = ":domain" @@ -316,6 +375,8 @@ func (srv *Server) ListenAndServe() error { if srv.UDPSize == 0 { srv.UDPSize = MinMsgSize } + srv.queue = make(chan *response) + defer close(srv.queue) switch srv.Net { case "tcp", "tcp4", "tcp6": a, err := net.ResolveTCPAddr(srv.Net, addr) @@ -380,8 +441,11 @@ func (srv *Server) ActivateAndServe() error { if srv.started { return &Error{err: "server already started"} } + pConn := srv.PacketConn l := srv.Listener + srv.queue = make(chan *response) + defer close(srv.queue) if pConn != nil { if srv.UDPSize == 0 { srv.UDPSize = MinMsgSize @@ -439,7 +503,6 @@ func (srv *Server) getReadTimeout() time.Duration { } // serveTCP starts a TCP listener for the server. -// Each request is handled in a separate goroutine. func (srv *Server) serveTCP(l net.Listener) error { defer l.Close() @@ -447,26 +510,8 @@ func (srv *Server) serveTCP(l net.Listener) error { srv.NotifyStartedFunc() } - reader := Reader(&defaultReader{srv}) - if srv.DecorateReader != nil { - reader = srv.DecorateReader(reader) - } - - handler := srv.Handler - if handler == nil { - handler = DefaultServeMux - } - rtimeout := srv.getReadTimeout() - // deadline is not used here for { rw, err := l.Accept() - if err != nil { - if neterr, ok := err.(net.Error); ok && neterr.Temporary() { - continue - } - return err - } - m, err := reader.ReadTCP(rw, rtimeout) srv.lock.RLock() if !srv.started { srv.lock.RUnlock() @@ -474,14 +519,16 @@ func (srv *Server) serveTCP(l net.Listener) error { } srv.lock.RUnlock() if err != nil { - continue + if neterr, ok := err.(net.Error); ok && neterr.Temporary() { + continue + } + return err } - go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw) + srv.spawnWorker(&response{tsigSecret: srv.TsigSecret, tcp: rw}) } } // serveUDP starts a UDP listener for the server. -// Each request is handled in a separate goroutine. func (srv *Server) serveUDP(l *net.UDPConn) error { defer l.Close() @@ -494,10 +541,6 @@ func (srv *Server) serveUDP(l *net.UDPConn) error { reader = srv.DecorateReader(reader) } - handler := srv.Handler - if handler == nil { - handler = DefaultServeMux - } rtimeout := srv.getReadTimeout() // deadline is not used here for { @@ -517,80 +560,98 @@ func (srv *Server) serveUDP(l *net.UDPConn) error { if len(m) < headerSize { continue } - go srv.serve(s.RemoteAddr(), handler, m, l, s, nil) + srv.spawnWorker(&response{msg: m, tsigSecret: srv.TsigSecret, udp: l, udpSession: s}) } } -// Serve a new connection. -func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) { - w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s} +func (srv *Server) serve(w *response) { if srv.DecorateWriter != nil { w.writer = srv.DecorateWriter(w) } else { w.writer = w } - q := 0 // counter for the amount of TCP queries we get + if w.udp != nil { + // serve UDP + srv.serveDNS(w) + return + } reader := Reader(&defaultReader{srv}) if srv.DecorateReader != nil { reader = srv.DecorateReader(reader) } -Redo: + + defer func() { + if !w.hijacked { + w.Close() + } + }() + + idleTimeout := tcpIdleTimeout + if srv.IdleTimeout != nil { + idleTimeout = srv.IdleTimeout() + } + + timeout := srv.getReadTimeout() + + limit := srv.MaxTCPQueries + if limit == 0 { + limit = maxTCPQueries + } + + for q := 0; q < limit || limit == -1; q++ { + var err error + w.msg, err = reader.ReadTCP(w.tcp, timeout) + if err != nil { + // TODO(tmthrgd): handle error + break + } + srv.serveDNS(w) + if w.tcp == nil { + break // Close() was called + } + if w.hijacked { + break // client will call Close() themselves + } + // The first read uses the read timeout, the rest use the + // idle timeout. + timeout = idleTimeout + } +} + +func (srv *Server) serveDNS(w *response) { req := new(Msg) - err := req.Unpack(m) + err := req.Unpack(w.msg) if err != nil { // Send a FormatError back x := new(Msg) x.SetRcodeFormatError(req) w.WriteMsg(x) - goto Exit + return } if !srv.Unsafe && req.Response { - goto Exit + return } w.tsigStatus = nil if w.tsigSecret != nil { if t := req.IsTsig(); t != nil { - secret := t.Hdr.Name - if _, ok := w.tsigSecret[secret]; !ok { - w.tsigStatus = ErrKeyAlg + if secret, ok := w.tsigSecret[t.Hdr.Name]; ok { + w.tsigStatus = TsigVerify(w.msg, secret, "", false) + } else { + w.tsigStatus = ErrSecret } - w.tsigStatus = TsigVerify(m, w.tsigSecret[secret], "", false) w.tsigTimersOnly = false w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC } } - h.ServeDNS(w, req) // Writes back to the client -Exit: - if w.tcp == nil { - return - } - // TODO(miek): make this number configurable? - if q > maxTCPQueries { // close socket after this many queries - w.Close() - return + handler := srv.Handler + if handler == nil { + handler = DefaultServeMux } - if w.hijacked { - return // client calls Close() - } - if u != nil { // UDP, "close" and return - w.Close() - return - } - idleTimeout := tcpIdleTimeout - if srv.IdleTimeout != nil { - idleTimeout = srv.IdleTimeout() - } - m, err = reader.ReadTCP(w.tcp, idleTimeout) - if err == nil { - q++ - goto Redo - } - w.Close() - return + handler.ServeDNS(w, req) // Writes back to the client } func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { @@ -693,7 +754,12 @@ func (w *response) LocalAddr() net.Addr { } // RemoteAddr implements the ResponseWriter.RemoteAddr method. -func (w *response) RemoteAddr() net.Addr { return w.remoteAddr } +func (w *response) RemoteAddr() net.Addr { + if w.tcp != nil { + return w.tcp.RemoteAddr() + } + return w.udpSession.RemoteAddr() +} // TsigStatus implements the ResponseWriter.TsigStatus method. func (w *response) TsigStatus() error { return w.tsigStatus } diff --git a/vendor/github.com/miekg/dns/server_test.go b/vendor/github.com/miekg/dns/server_test.go index 7693e76..6fc9e88 100644 --- a/vendor/github.com/miekg/dns/server_test.go +++ b/vendor/github.com/miekg/dns/server_test.go @@ -55,7 +55,7 @@ func RunLocalUDPServer(laddr string) (*Server, string, error) { return server, l, err } -func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan struct{}, error) { +func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan error, error) { pc, err := net.ListenPacket("udp", laddr) if err != nil { return nil, "", nil, err @@ -66,11 +66,13 @@ func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan struct{}, waitLock.Lock() server.NotifyStartedFunc = waitLock.Unlock - fin := make(chan struct{}, 0) + // fin must be buffered so the goroutine below won't block + // forever if fin is never read from. This always happens + // in RunLocalUDPServer and can happen in TestShutdownUDP. + fin := make(chan error, 1) go func() { - server.ActivateAndServe() - close(fin) + fin <- server.ActivateAndServe() pc.Close() }() @@ -100,9 +102,15 @@ func RunLocalUDPServerUnsafe(laddr string) (*Server, string, error) { } func RunLocalTCPServer(laddr string) (*Server, string, error) { + server, l, _, err := RunLocalTCPServerWithFinChan(laddr) + + return server, l, err +} + +func RunLocalTCPServerWithFinChan(laddr string) (*Server, string, chan error, error) { l, err := net.Listen("tcp", laddr) if err != nil { - return nil, "", err + return nil, "", nil, err } server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour} @@ -111,13 +119,17 @@ func RunLocalTCPServer(laddr string) (*Server, string, error) { waitLock.Lock() server.NotifyStartedFunc = waitLock.Unlock + // See the comment in RunLocalUDPServerWithFinChan as to + // why fin must be buffered. + fin := make(chan error, 1) + go func() { - server.ActivateAndServe() + fin <- server.ActivateAndServe() l.Close() }() waitLock.Lock() - return server, l.Addr().String(), nil + return server, l.Addr().String(), fin, nil } func RunLocalTLSServer(laddr string, config *tls.Config) (*Server, string, error) { @@ -545,13 +557,21 @@ func TestServingResponse(t *testing.T) { } func TestShutdownTCP(t *testing.T) { - s, _, err := RunLocalTCPServer(":0") + s, _, fin, err := RunLocalTCPServerWithFinChan(":0") if err != nil { t.Fatalf("unable to run test server: %v", err) } err = s.Shutdown() if err != nil { - t.Errorf("could not shutdown test TCP server, %v", err) + t.Fatalf("could not shutdown test TCP server, %v", err) + } + select { + case err := <-fin: + if err != nil { + t.Errorf("error returned from ActivateAndServe, %v", err) + } + case <-time.After(2 * time.Second): + t.Error("could not shutdown test TCP server. Gave up waiting") } } @@ -642,7 +662,10 @@ func TestShutdownUDP(t *testing.T) { t.Errorf("could not shutdown test UDP server, %v", err) } select { - case <-fin: + case err := <-fin: + if err != nil { + t.Errorf("error returned from ActivateAndServe, %v", err) + } case <-time.After(2 * time.Second): t.Error("could not shutdown test UDP server. Gave up waiting") } diff --git a/vendor/github.com/miekg/dns/types_generate.go b/vendor/github.com/miekg/dns/types_generate.go index 8703cce..b8db4f3 100644 --- a/vendor/github.com/miekg/dns/types_generate.go +++ b/vendor/github.com/miekg/dns/types_generate.go @@ -226,7 +226,7 @@ func main() { continue } fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name) - fields := []string{"*rr.Hdr.copyHeader()"} + fields := []string{"rr.Hdr"} for i := 1; i < st.NumFields(); i++ { f := st.Field(i).Name() if sl, ok := st.Field(i).Type().(*types.Slice); ok { diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go index f3f31a7..a4826ee 100644 --- a/vendor/github.com/miekg/dns/udp.go +++ b/vendor/github.com/miekg/dns/udp.go @@ -9,6 +9,22 @@ import ( "golang.org/x/net/ipv6" ) +// This is the required size of the OOB buffer to pass to ReadMsgUDP. +var udpOOBSize = func() int { + // We can't know whether we'll get an IPv4 control message or an + // IPv6 control message ahead of time. To get around this, we size + // the buffer equal to the largest of the two. + + oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface) + oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface) + + if len(oob4) > len(oob6) { + return len(oob4) + } + + return len(oob6) +}() + // SessionUDP holds the remote address and the associated // out-of-band data. type SessionUDP struct { @@ -22,7 +38,7 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr } // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a // net.UDPAddr. func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { - oob := make([]byte, 40) + oob := make([]byte, udpOOBSize) n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob) if err != nil { return n, nil, err @@ -53,18 +69,15 @@ func parseDstFromOOB(oob []byte) net.IP { // Start with IPv6 and then fallback to IPv4 // TODO(fastest963): Figure out a way to prefer one or the other. Looking at // the lvl of the header for a 0 or 41 isn't cross-platform. - var dst net.IP cm6 := new(ipv6.ControlMessage) - if cm6.Parse(oob) == nil { - dst = cm6.Dst + if cm6.Parse(oob) == nil && cm6.Dst != nil { + return cm6.Dst } - if dst == nil { - cm4 := new(ipv4.ControlMessage) - if cm4.Parse(oob) == nil { - dst = cm4.Dst - } + cm4 := new(ipv4.ControlMessage) + if cm4.Parse(oob) == nil && cm4.Dst != nil { + return cm4.Dst } - return dst + return nil } // correctSource takes oob data and returns new oob data with the Src equal to the Dst diff --git a/vendor/github.com/miekg/dns/udp_test.go b/vendor/github.com/miekg/dns/udp_test.go index 2c145db..f27d79d 100644 --- a/vendor/github.com/miekg/dns/udp_test.go +++ b/vendor/github.com/miekg/dns/udp_test.go @@ -5,6 +5,7 @@ package dns import ( "bytes" "net" + "runtime" "strings" "testing" "time" @@ -74,6 +75,14 @@ func TestSetUDPSocketOptions(t *testing.T) { } func TestParseDstFromOOB(t *testing.T) { + if runtime.GOARCH != "amd64" { + // The cmsghdr struct differs in the width (32/64-bit) of + // lengths and the struct padding between architectures. + // The data below was only written with amd64 in mind, and + // thus the test must be skipped on other architectures. + t.Skip("skipping test on unsupported architecture") + } + // dst is :ffff:100.100.100.100 oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0} dst := parseDstFromOOB(oob) @@ -106,6 +115,11 @@ func TestParseDstFromOOB(t *testing.T) { } func TestCorrectSource(t *testing.T) { + if runtime.GOARCH != "amd64" { + // See comment above in TestParseDstFromOOB. + t.Skip("skipping test on unsupported architecture") + } + // dst is :ffff:100.100.100.100 which should be counted as IPv4 oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0} soob := correctSource(oob) diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index 0e23cc3..dcc84e4 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = V{1, 0, 3} +var Version = V{1, 0, 8} // V holds the version of this library. type V struct { diff --git a/vendor/github.com/miekg/dns/zcompress.go b/vendor/github.com/miekg/dns/zcompress.go index c250320..a2c09dd 100644 --- a/vendor/github.com/miekg/dns/zcompress.go +++ b/vendor/github.com/miekg/dns/zcompress.go @@ -2,117 +2,154 @@ package dns -func compressionLenHelperType(c map[string]int, r RR) { +func compressionLenHelperType(c map[string]int, r RR, initLen int) int { + currentLen := initLen switch x := r.(type) { case *AFSDB: - compressionLenHelper(c, x.Hostname) + currentLen -= len(x.Hostname) + 1 + currentLen += compressionLenHelper(c, x.Hostname, currentLen) case *CNAME: - compressionLenHelper(c, x.Target) + currentLen -= len(x.Target) + 1 + currentLen += compressionLenHelper(c, x.Target, currentLen) case *DNAME: - compressionLenHelper(c, x.Target) + currentLen -= len(x.Target) + 1 + currentLen += compressionLenHelper(c, x.Target, currentLen) case *HIP: for i := range x.RendezvousServers { - compressionLenHelper(c, x.RendezvousServers[i]) + currentLen -= len(x.RendezvousServers[i]) + 1 + } + for i := range x.RendezvousServers { + currentLen += compressionLenHelper(c, x.RendezvousServers[i], currentLen) } case *KX: - compressionLenHelper(c, x.Exchanger) + currentLen -= len(x.Exchanger) + 1 + currentLen += compressionLenHelper(c, x.Exchanger, currentLen) case *LP: - compressionLenHelper(c, x.Fqdn) + currentLen -= len(x.Fqdn) + 1 + currentLen += compressionLenHelper(c, x.Fqdn, currentLen) case *MB: - compressionLenHelper(c, x.Mb) + currentLen -= len(x.Mb) + 1 + currentLen += compressionLenHelper(c, x.Mb, currentLen) case *MD: - compressionLenHelper(c, x.Md) + currentLen -= len(x.Md) + 1 + currentLen += compressionLenHelper(c, x.Md, currentLen) case *MF: - compressionLenHelper(c, x.Mf) + currentLen -= len(x.Mf) + 1 + currentLen += compressionLenHelper(c, x.Mf, currentLen) case *MG: - compressionLenHelper(c, x.Mg) + currentLen -= len(x.Mg) + 1 + currentLen += compressionLenHelper(c, x.Mg, currentLen) case *MINFO: - compressionLenHelper(c, x.Rmail) - compressionLenHelper(c, x.Email) + currentLen -= len(x.Rmail) + 1 + currentLen += compressionLenHelper(c, x.Rmail, currentLen) + currentLen -= len(x.Email) + 1 + currentLen += compressionLenHelper(c, x.Email, currentLen) case *MR: - compressionLenHelper(c, x.Mr) + currentLen -= len(x.Mr) + 1 + currentLen += compressionLenHelper(c, x.Mr, currentLen) case *MX: - compressionLenHelper(c, x.Mx) + currentLen -= len(x.Mx) + 1 + currentLen += compressionLenHelper(c, x.Mx, currentLen) case *NAPTR: - compressionLenHelper(c, x.Replacement) + currentLen -= len(x.Replacement) + 1 + currentLen += compressionLenHelper(c, x.Replacement, currentLen) case *NS: - compressionLenHelper(c, x.Ns) + currentLen -= len(x.Ns) + 1 + currentLen += compressionLenHelper(c, x.Ns, currentLen) case *NSAPPTR: - compressionLenHelper(c, x.Ptr) + currentLen -= len(x.Ptr) + 1 + currentLen += compressionLenHelper(c, x.Ptr, currentLen) case *NSEC: - compressionLenHelper(c, x.NextDomain) + currentLen -= len(x.NextDomain) + 1 + currentLen += compressionLenHelper(c, x.NextDomain, currentLen) case *PTR: - compressionLenHelper(c, x.Ptr) + currentLen -= len(x.Ptr) + 1 + currentLen += compressionLenHelper(c, x.Ptr, currentLen) case *PX: - compressionLenHelper(c, x.Map822) - compressionLenHelper(c, x.Mapx400) + currentLen -= len(x.Map822) + 1 + currentLen += compressionLenHelper(c, x.Map822, currentLen) + currentLen -= len(x.Mapx400) + 1 + currentLen += compressionLenHelper(c, x.Mapx400, currentLen) case *RP: - compressionLenHelper(c, x.Mbox) - compressionLenHelper(c, x.Txt) + currentLen -= len(x.Mbox) + 1 + currentLen += compressionLenHelper(c, x.Mbox, currentLen) + currentLen -= len(x.Txt) + 1 + currentLen += compressionLenHelper(c, x.Txt, currentLen) case *RRSIG: - compressionLenHelper(c, x.SignerName) + currentLen -= len(x.SignerName) + 1 + currentLen += compressionLenHelper(c, x.SignerName, currentLen) case *RT: - compressionLenHelper(c, x.Host) + currentLen -= len(x.Host) + 1 + currentLen += compressionLenHelper(c, x.Host, currentLen) case *SIG: - compressionLenHelper(c, x.SignerName) + currentLen -= len(x.SignerName) + 1 + currentLen += compressionLenHelper(c, x.SignerName, currentLen) case *SOA: - compressionLenHelper(c, x.Ns) - compressionLenHelper(c, x.Mbox) + currentLen -= len(x.Ns) + 1 + currentLen += compressionLenHelper(c, x.Ns, currentLen) + currentLen -= len(x.Mbox) + 1 + currentLen += compressionLenHelper(c, x.Mbox, currentLen) case *SRV: - compressionLenHelper(c, x.Target) + currentLen -= len(x.Target) + 1 + currentLen += compressionLenHelper(c, x.Target, currentLen) case *TALINK: - compressionLenHelper(c, x.PreviousName) - compressionLenHelper(c, x.NextName) + currentLen -= len(x.PreviousName) + 1 + currentLen += compressionLenHelper(c, x.PreviousName, currentLen) + currentLen -= len(x.NextName) + 1 + currentLen += compressionLenHelper(c, x.NextName, currentLen) case *TKEY: - compressionLenHelper(c, x.Algorithm) + currentLen -= len(x.Algorithm) + 1 + currentLen += compressionLenHelper(c, x.Algorithm, currentLen) case *TSIG: - compressionLenHelper(c, x.Algorithm) + currentLen -= len(x.Algorithm) + 1 + currentLen += compressionLenHelper(c, x.Algorithm, currentLen) } + return currentLen - initLen } -func compressionLenSearchType(c map[string]int, r RR) (int, bool) { +func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) { switch x := r.(type) { case *AFSDB: - k1, ok1 := compressionLenSearch(c, x.Hostname) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Hostname) + return k1, ok1, sz1 case *CNAME: - k1, ok1 := compressionLenSearch(c, x.Target) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Target) + return k1, ok1, sz1 case *MB: - k1, ok1 := compressionLenSearch(c, x.Mb) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Mb) + return k1, ok1, sz1 case *MD: - k1, ok1 := compressionLenSearch(c, x.Md) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Md) + return k1, ok1, sz1 case *MF: - k1, ok1 := compressionLenSearch(c, x.Mf) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Mf) + return k1, ok1, sz1 case *MG: - k1, ok1 := compressionLenSearch(c, x.Mg) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Mg) + return k1, ok1, sz1 case *MINFO: - k1, ok1 := compressionLenSearch(c, x.Rmail) - k2, ok2 := compressionLenSearch(c, x.Email) - return k1 + k2, ok1 && ok2 + k1, ok1, sz1 := compressionLenSearch(c, x.Rmail) + k2, ok2, sz2 := compressionLenSearch(c, x.Email) + return k1 + k2, ok1 && ok2, sz1 + sz2 case *MR: - k1, ok1 := compressionLenSearch(c, x.Mr) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Mr) + return k1, ok1, sz1 case *MX: - k1, ok1 := compressionLenSearch(c, x.Mx) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Mx) + return k1, ok1, sz1 case *NS: - k1, ok1 := compressionLenSearch(c, x.Ns) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Ns) + return k1, ok1, sz1 case *PTR: - k1, ok1 := compressionLenSearch(c, x.Ptr) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Ptr) + return k1, ok1, sz1 case *RT: - k1, ok1 := compressionLenSearch(c, x.Host) - return k1, ok1 + k1, ok1, sz1 := compressionLenSearch(c, x.Host) + return k1, ok1, sz1 case *SOA: - k1, ok1 := compressionLenSearch(c, x.Ns) - k2, ok2 := compressionLenSearch(c, x.Mbox) - return k1 + k2, ok1 && ok2 + k1, ok1, sz1 := compressionLenSearch(c, x.Ns) + k2, ok2, sz2 := compressionLenSearch(c, x.Mbox) + return k1 + k2, ok1 && ok2, sz1 + sz2 } - return 0, false + return 0, false, 0 } diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go index abd75dd..965753b 100644 --- a/vendor/github.com/miekg/dns/ztypes.go +++ b/vendor/github.com/miekg/dns/ztypes.go @@ -649,215 +649,215 @@ func (rr *X25) len() int { // copy() functions func (rr *A) copy() RR { - return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)} + return &A{rr.Hdr, copyIP(rr.A)} } func (rr *AAAA) copy() RR { - return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)} + return &AAAA{rr.Hdr, copyIP(rr.AAAA)} } func (rr *AFSDB) copy() RR { - return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname} + return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname} } func (rr *ANY) copy() RR { - return &ANY{*rr.Hdr.copyHeader()} + return &ANY{rr.Hdr} } func (rr *AVC) copy() RR { Txt := make([]string, len(rr.Txt)) copy(Txt, rr.Txt) - return &AVC{*rr.Hdr.copyHeader(), Txt} + return &AVC{rr.Hdr, Txt} } func (rr *CAA) copy() RR { - return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value} + return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value} } func (rr *CERT) copy() RR { - return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} + return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} } func (rr *CNAME) copy() RR { - return &CNAME{*rr.Hdr.copyHeader(), rr.Target} + return &CNAME{rr.Hdr, rr.Target} } func (rr *CSYNC) copy() RR { TypeBitMap := make([]uint16, len(rr.TypeBitMap)) copy(TypeBitMap, rr.TypeBitMap) - return &CSYNC{*rr.Hdr.copyHeader(), rr.Serial, rr.Flags, TypeBitMap} + return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap} } func (rr *DHCID) copy() RR { - return &DHCID{*rr.Hdr.copyHeader(), rr.Digest} + return &DHCID{rr.Hdr, rr.Digest} } func (rr *DNAME) copy() RR { - return &DNAME{*rr.Hdr.copyHeader(), rr.Target} + return &DNAME{rr.Hdr, rr.Target} } func (rr *DNSKEY) copy() RR { - return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} + return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} } func (rr *DS) copy() RR { - return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} + return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} } func (rr *EID) copy() RR { - return &EID{*rr.Hdr.copyHeader(), rr.Endpoint} + return &EID{rr.Hdr, rr.Endpoint} } func (rr *EUI48) copy() RR { - return &EUI48{*rr.Hdr.copyHeader(), rr.Address} + return &EUI48{rr.Hdr, rr.Address} } func (rr *EUI64) copy() RR { - return &EUI64{*rr.Hdr.copyHeader(), rr.Address} + return &EUI64{rr.Hdr, rr.Address} } func (rr *GID) copy() RR { - return &GID{*rr.Hdr.copyHeader(), rr.Gid} + return &GID{rr.Hdr, rr.Gid} } func (rr *GPOS) copy() RR { - return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude} + return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude} } func (rr *HINFO) copy() RR { - return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os} + return &HINFO{rr.Hdr, rr.Cpu, rr.Os} } func (rr *HIP) copy() RR { RendezvousServers := make([]string, len(rr.RendezvousServers)) copy(RendezvousServers, rr.RendezvousServers) - return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} + return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} } func (rr *KX) copy() RR { - return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger} + return &KX{rr.Hdr, rr.Preference, rr.Exchanger} } func (rr *L32) copy() RR { - return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)} + return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)} } func (rr *L64) copy() RR { - return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64} + return &L64{rr.Hdr, rr.Preference, rr.Locator64} } func (rr *LOC) copy() RR { - return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude} + return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude} } func (rr *LP) copy() RR { - return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn} + return &LP{rr.Hdr, rr.Preference, rr.Fqdn} } func (rr *MB) copy() RR { - return &MB{*rr.Hdr.copyHeader(), rr.Mb} + return &MB{rr.Hdr, rr.Mb} } func (rr *MD) copy() RR { - return &MD{*rr.Hdr.copyHeader(), rr.Md} + return &MD{rr.Hdr, rr.Md} } func (rr *MF) copy() RR { - return &MF{*rr.Hdr.copyHeader(), rr.Mf} + return &MF{rr.Hdr, rr.Mf} } func (rr *MG) copy() RR { - return &MG{*rr.Hdr.copyHeader(), rr.Mg} + return &MG{rr.Hdr, rr.Mg} } func (rr *MINFO) copy() RR { - return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email} + return &MINFO{rr.Hdr, rr.Rmail, rr.Email} } func (rr *MR) copy() RR { - return &MR{*rr.Hdr.copyHeader(), rr.Mr} + return &MR{rr.Hdr, rr.Mr} } func (rr *MX) copy() RR { - return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx} + return &MX{rr.Hdr, rr.Preference, rr.Mx} } func (rr *NAPTR) copy() RR { - return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement} + return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement} } func (rr *NID) copy() RR { - return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID} + return &NID{rr.Hdr, rr.Preference, rr.NodeID} } func (rr *NIMLOC) copy() RR { - return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator} + return &NIMLOC{rr.Hdr, rr.Locator} } func (rr *NINFO) copy() RR { ZSData := make([]string, len(rr.ZSData)) copy(ZSData, rr.ZSData) - return &NINFO{*rr.Hdr.copyHeader(), ZSData} + return &NINFO{rr.Hdr, ZSData} } func (rr *NS) copy() RR { - return &NS{*rr.Hdr.copyHeader(), rr.Ns} + return &NS{rr.Hdr, rr.Ns} } func (rr *NSAPPTR) copy() RR { - return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr} + return &NSAPPTR{rr.Hdr, rr.Ptr} } func (rr *NSEC) copy() RR { TypeBitMap := make([]uint16, len(rr.TypeBitMap)) copy(TypeBitMap, rr.TypeBitMap) - return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap} + return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap} } func (rr *NSEC3) copy() RR { TypeBitMap := make([]uint16, len(rr.TypeBitMap)) copy(TypeBitMap, rr.TypeBitMap) - return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap} + return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap} } func (rr *NSEC3PARAM) copy() RR { - return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt} + return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt} } func (rr *OPENPGPKEY) copy() RR { - return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey} + return &OPENPGPKEY{rr.Hdr, rr.PublicKey} } func (rr *OPT) copy() RR { Option := make([]EDNS0, len(rr.Option)) copy(Option, rr.Option) - return &OPT{*rr.Hdr.copyHeader(), Option} + return &OPT{rr.Hdr, Option} } func (rr *PTR) copy() RR { - return &PTR{*rr.Hdr.copyHeader(), rr.Ptr} + return &PTR{rr.Hdr, rr.Ptr} } func (rr *PX) copy() RR { - return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400} + return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400} } func (rr *RFC3597) copy() RR { - return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata} + return &RFC3597{rr.Hdr, rr.Rdata} } func (rr *RKEY) copy() RR { - return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} + return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} } func (rr *RP) copy() RR { - return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt} + return &RP{rr.Hdr, rr.Mbox, rr.Txt} } func (rr *RRSIG) copy() RR { - return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature} + return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature} } func (rr *RT) copy() RR { - return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host} + return &RT{rr.Hdr, rr.Preference, rr.Host} } func (rr *SMIMEA) copy() RR { - return &SMIMEA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} + return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} } func (rr *SOA) copy() RR { - return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl} + return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl} } func (rr *SPF) copy() RR { Txt := make([]string, len(rr.Txt)) copy(Txt, rr.Txt) - return &SPF{*rr.Hdr.copyHeader(), Txt} + return &SPF{rr.Hdr, Txt} } func (rr *SRV) copy() RR { - return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target} + return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target} } func (rr *SSHFP) copy() RR { - return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint} + return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint} } func (rr *TA) copy() RR { - return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} + return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} } func (rr *TALINK) copy() RR { - return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName} + return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName} } func (rr *TKEY) copy() RR { - return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData} + return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData} } func (rr *TLSA) copy() RR { - return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} + return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} } func (rr *TSIG) copy() RR { - return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData} + return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData} } func (rr *TXT) copy() RR { Txt := make([]string, len(rr.Txt)) copy(Txt, rr.Txt) - return &TXT{*rr.Hdr.copyHeader(), Txt} + return &TXT{rr.Hdr, Txt} } func (rr *UID) copy() RR { - return &UID{*rr.Hdr.copyHeader(), rr.Uid} + return &UID{rr.Hdr, rr.Uid} } func (rr *UINFO) copy() RR { - return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo} + return &UINFO{rr.Hdr, rr.Uinfo} } func (rr *URI) copy() RR { - return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target} + return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target} } func (rr *X25) copy() RR { - return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress} + return &X25{rr.Hdr, rr.PSDNAddress} } diff --git a/vendor/github.com/rs/cors/.travis.yml b/vendor/github.com/rs/cors/.travis.yml index 3baa364..17e5e50 100644 --- a/vendor/github.com/rs/cors/.travis.yml +++ b/vendor/github.com/rs/cors/.travis.yml @@ -1,6 +1,7 @@ language: go go: -- 1.8 +- 1.9 +- "1.10" - tip matrix: allow_failures: diff --git a/vendor/github.com/rs/cors/README.md b/vendor/github.com/rs/cors/README.md index 9e74902..87413cc 100644 --- a/vendor/github.com/rs/cors/README.md +++ b/vendor/github.com/rs/cors/README.md @@ -49,6 +49,14 @@ The server now runs on `localhost:8080`: {"hello": "world"} +### Allow * With Credentials Security Protection + +This library has been modified to avoid a well known security issue when configured with `AllowedOrigins` to `*` and `AllowCredentials` to `true`. Such setup used to make the library reflects the request `Origin` header value, working around a security protection embedded into the standard that makes clients to refuse such configuration. This behavior has been removed with [#55](https://github.com/rs/cors/issues/55) and [#57](https://github.com/rs/cors/issues/57). + +If you depend on this behavior and understand the implications, you can restore it using the `AllowOriginFunc` with `func(origin string) {return true}`. + +Please refer to [#55](https://github.com/rs/cors/issues/55) for more information about the security implications. + ### More Examples * `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go) @@ -57,6 +65,9 @@ The server now runs on `localhost:8080`: * [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go) * [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go) * [HttpRouter](https://github.com/julienschmidt/httprouter): [examples/httprouter/server.go](https://github.com/rs/cors/blob/master/examples/httprouter/server.go) +* [Gorilla](http://www.gorillatoolkit.org/pkg/mux): [examples/gorilla/server.go](https://github.com/rs/cors/blob/master/examples/gorilla/server.go) +* [Buffalo](https://gobuffalo.io): [examples/buffalo/server.go](https://github.com/rs/cors/blob/master/examples/buffalo/server.go) +* [Gin](https://gin-gonic.github.io/gin): [examples/gin/server.go](https://github.com/rs/cors/blob/master/examples/gin/server.go) ## Parameters @@ -64,8 +75,10 @@ Parameters are passed to the middleware thru the `cors.New` method as follow: ```go c := cors.New(cors.Options{ - AllowedOrigins: []string{"http://foo.com"}, + AllowedOrigins: []string{"http://foo.com", "http://foo.com:8080"}, AllowCredentials: true, + // Enable Debugging for testing, consider disabling in production + Debug: true, }) // Insert the middleware diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go index 8179c61..1518108 100644 --- a/vendor/github.com/rs/cors/cors.go +++ b/vendor/github.com/rs/cors/cors.go @@ -42,7 +42,7 @@ type Options struct { // set, the content of AllowedOrigins is ignored. AllowOriginFunc func(origin string) bool // AllowedMethods is a list of methods the client is allowed to use with - // cross-domain requests. Default value is simple methods (GET and POST) + // cross-domain requests. Default value is simple methods (HEAD, GET and POST). AllowedMethods []string // AllowedHeaders is list of non simple headers the client is allowed to use with // cross-domain requests. @@ -52,12 +52,12 @@ type Options struct { // ExposedHeaders indicates which headers are safe to expose to the API of a CORS // API specification ExposedHeaders []string - // AllowCredentials indicates whether the request can include user credentials like - // cookies, HTTP authentication or client side SSL certificates. - AllowCredentials bool // MaxAge indicates how long (in seconds) the results of a preflight request // can be cached MaxAge int + // AllowCredentials indicates whether the request can include user credentials like + // cookies, HTTP authentication or client side SSL certificates. + AllowCredentials bool // OptionsPassthrough instructs preflight to let other potential next handlers to // process the OPTIONS method. Turn this on if your application handles OPTIONS. OptionsPassthrough bool @@ -69,24 +69,24 @@ type Options struct { type Cors struct { // Debug logger Log *log.Logger - // Set to true when allowed origins contains a "*" - allowedOriginsAll bool // Normalized list of plain allowed origins allowedOrigins []string // List of allowed origins containing wildcards allowedWOrigins []wildcard // Optional origin validator function allowOriginFunc func(origin string) bool - // Set to true when allowed headers contains a "*" - allowedHeadersAll bool // Normalized list of allowed headers allowedHeaders []string // Normalized list of allowed methods allowedMethods []string // Normalized list of exposed headers - exposedHeaders []string + exposedHeaders []string + maxAge int + // Set to true when allowed origins contains a "*" + allowedOriginsAll bool + // Set to true when allowed headers contains a "*" + allowedHeadersAll bool allowCredentials bool - maxAge int optionPassthrough bool } @@ -127,7 +127,7 @@ func New(options Options) *Cors { break } else if i := strings.IndexByte(origin, '*'); i >= 0 { // Split the origin in two: start and end string without the * - w := wildcard{origin[0:i], origin[i+1 : len(origin)]} + w := wildcard{origin[0:i], origin[i+1:]} c.allowedWOrigins = append(c.allowedWOrigins, w) } else { c.allowedOrigins = append(c.allowedOrigins, origin) @@ -138,7 +138,7 @@ func New(options Options) *Cors { // Allowed Headers if len(options.AllowedHeaders) == 0 { // Use sensible defaults - c.allowedHeaders = []string{"Origin", "Accept", "Content-Type"} + c.allowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With"} } else { // Origin is always appended as some browsers will always request for this header at preflight c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey) @@ -154,7 +154,7 @@ func New(options Options) *Cors { // Allowed Methods if len(options.AllowedMethods) == 0 { // Default is spec's "simple" methods - c.allowedMethods = []string{"GET", "POST"} + c.allowedMethods = []string{"GET", "POST", "HEAD"} } else { c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) } @@ -174,7 +174,7 @@ func AllowAll() *Cors { AllowedOrigins: []string{"*"}, AllowedMethods: []string{"HEAD", "GET", "POST", "PUT", "PATCH", "DELETE"}, AllowedHeaders: []string{"*"}, - AllowCredentials: true, + AllowCredentials: false, }) } @@ -182,7 +182,7 @@ func AllowAll() *Cors { // as necessary. func (c *Cors) Handler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("Handler: Preflight request") c.handlePreflight(w, r) // Preflight requests are standalone and should stop the chain as some other @@ -204,7 +204,7 @@ func (c *Cors) Handler(h http.Handler) http.Handler { // HandlerFunc provides Martini compatible handler func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("HandlerFunc: Preflight request") c.handlePreflight(w, r) } else { @@ -215,7 +215,7 @@ func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) { // Negroni compatible interface func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("ServeHTTP: Preflight request") c.handlePreflight(w, r) // Preflight requests are standalone and should stop the chain as some other @@ -239,7 +239,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") - if r.Method != "OPTIONS" { + if r.Method != http.MethodOptions { c.logf(" Preflight aborted: %s!=OPTIONS", r.Method) return } @@ -269,7 +269,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) return } - if c.allowedOriginsAll && !c.allowCredentials { + if c.allowedOriginsAll { headers.Set("Access-Control-Allow-Origin", "*") } else { headers.Set("Access-Control-Allow-Origin", origin) @@ -297,7 +297,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") - if r.Method == "OPTIONS" { + if r.Method == http.MethodOptions { c.logf(" Actual request no headers added: method == %s", r.Method) return } @@ -321,7 +321,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { return } - if c.allowedOriginsAll && !c.allowCredentials { + if c.allowedOriginsAll { headers.Set("Access-Control-Allow-Origin", "*") } else { headers.Set("Access-Control-Allow-Origin", origin) @@ -373,7 +373,7 @@ func (c *Cors) isMethodAllowed(method string) bool { return false } method = strings.ToUpper(method) - if method == "OPTIONS" { + if method == http.MethodOptions { // Always allow preflight requests return true } diff --git a/vendor/github.com/rs/cors/cors_test.go b/vendor/github.com/rs/cors/cors_test.go index 916c101..d3dbcba 100644 --- a/vendor/github.com/rs/cors/cors_test.go +++ b/vendor/github.com/rs/cors/cors_test.go @@ -83,7 +83,7 @@ func TestSpec(t *testing.T) { }, map[string]string{ "Vary": "Origin", - "Access-Control-Allow-Origin": "http://foobar.com", + "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Credentials": "true", }, }, @@ -242,6 +242,25 @@ func TestSpec(t *testing.T) { "Access-Control-Allow-Headers": "X-Header-2, X-Header-1", }, }, + { + "DefaultAllowedHeaders", + Options{ + AllowedOrigins: []string{"http://foobar.com"}, + AllowedHeaders: []string{}, + }, + "OPTIONS", + map[string]string{ + "Origin": "http://foobar.com", + "Access-Control-Request-Method": "GET", + "Access-Control-Request-Headers": "X-Requested-With", + }, + map[string]string{ + "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers", + "Access-Control-Allow-Origin": "http://foobar.com", + "Access-Control-Allow-Methods": "GET", + "Access-Control-Allow-Headers": "X-Requested-With", + }, + }, { "AllowedWildcardHeader", Options{ @@ -411,7 +430,7 @@ func TestDefault(t *testing.T) { } } -func TestHandlePreflightInvlaidOriginAbortion(t *testing.T) { +func TestHandlePreflightInvalidOriginAbortion(t *testing.T) { s := New(Options{ AllowedOrigins: []string{"http://foo.com"}, }) @@ -451,7 +470,7 @@ func TestHandleActualRequestAbortsOptionsMethod(t *testing.T) { assertHeaders(t, res.Header(), map[string]string{}) } -func TestHandleActualRequestInvlaidOriginAbortion(t *testing.T) { +func TestHandleActualRequestInvalidOriginAbortion(t *testing.T) { s := New(Options{ AllowedOrigins: []string{"http://foo.com"}, }) @@ -466,7 +485,7 @@ func TestHandleActualRequestInvlaidOriginAbortion(t *testing.T) { }) } -func TestHandleActualRequestInvlaidMethodAbortion(t *testing.T) { +func TestHandleActualRequestInvalidMethodAbortion(t *testing.T) { s := New(Options{ AllowedMethods: []string{"POST"}, AllowCredentials: true, diff --git a/vendor/github.com/rs/cors/examples/buffalo/server.go b/vendor/github.com/rs/cors/examples/buffalo/server.go new file mode 100644 index 0000000..57a2445 --- /dev/null +++ b/vendor/github.com/rs/cors/examples/buffalo/server.go @@ -0,0 +1,36 @@ +package main + +import ( + "log" + + "github.com/gobuffalo/buffalo" + "github.com/gobuffalo/buffalo/render" + "github.com/rs/cors" +) + +var r *render.Engine + +func init() { + r = render.New(render.Options{}) +} + +func main() { + app := App() + if err := app.Serve(); err != nil { + log.Fatal(err) + } +} + +func App() *buffalo.App { + app := buffalo.New(buffalo.Options{ + PreWares: []buffalo.PreWare{cors.Default().Handler}, + }) + + app.GET("/", HomeHandler) + + return app +} + +func HomeHandler(c buffalo.Context) error { + return c.Render(200, r.JSON(map[string]string{"message": "Welcome to Buffalo!"})) +} diff --git a/vendor/github.com/rs/cors/examples/gin/server.go b/vendor/github.com/rs/cors/examples/gin/server.go new file mode 100644 index 0000000..a9d898e --- /dev/null +++ b/vendor/github.com/rs/cors/examples/gin/server.go @@ -0,0 +1,19 @@ +package main + +import ( + "net/http" + + "github.com/gin-gonic/gin" + cors "github.com/rs/cors/wrapper/gin" +) + +func main() { + router := gin.Default() + + router.Use(cors.Default()) + router.GET("/", func(context *gin.Context) { + context.JSON(http.StatusOK, gin.H{"hello": "world"}) + }) + + router.Run(":8080") +} diff --git a/vendor/github.com/rs/cors/go.mod b/vendor/github.com/rs/cors/go.mod new file mode 100644 index 0000000..0a4c652 --- /dev/null +++ b/vendor/github.com/rs/cors/go.mod @@ -0,0 +1 @@ +module github.com/rs/cors diff --git a/vendor/github.com/rs/cors/wrapper/gin/gin.go b/vendor/github.com/rs/cors/wrapper/gin/gin.go new file mode 100644 index 0000000..2c77541 --- /dev/null +++ b/vendor/github.com/rs/cors/wrapper/gin/gin.go @@ -0,0 +1,50 @@ +// Package cors/wrapper/gin provides gin.HandlerFunc to handle CORS related +// requests as a wrapper of github.com/rs/cors handler. +package gin + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/rs/cors" +) + +// Options is a configuration container to setup the CORS middleware. +type Options = cors.Options + +// corsWrapper is a wrapper of cors.Cors handler which preserves information +// about configured 'optionPassthrough' option. +type corsWrapper struct { + *cors.Cors + optionPassthrough bool +} + +// build transforms wrapped cors.Cors handler into Gin middleware. +func (c corsWrapper) build() gin.HandlerFunc { + return func(ctx *gin.Context) { + c.HandlerFunc(ctx.Writer, ctx.Request) + if !c.optionPassthrough && + ctx.Request.Method == http.MethodOptions && + ctx.GetHeader("Access-Control-Request-Method") != "" { + // Abort processing next Gin middlewares. + ctx.AbortWithStatus(http.StatusOK) + } + } +} + +// AllowAll creates a new CORS Gin middleware with permissive configuration +// allowing all origins with all standard methods with any header and +// credentials. +func AllowAll() gin.HandlerFunc { + return corsWrapper{Cors: cors.AllowAll()}.build() +} + +// Default creates a new CORS Gin middleware with default options. +func Default() gin.HandlerFunc { + return corsWrapper{Cors: cors.Default()}.build() +} + +// New creates a new CORS Gin middleware with the provided options. +func New(options Options) gin.HandlerFunc { + return corsWrapper{cors.New(options), options.OptionsPassthrough}.build() +} diff --git a/vendor/github.com/rs/cors/wrapper/gin/gin_test.go b/vendor/github.com/rs/cors/wrapper/gin/gin_test.go new file mode 100644 index 0000000..e9f8f75 --- /dev/null +++ b/vendor/github.com/rs/cors/wrapper/gin/gin_test.go @@ -0,0 +1,76 @@ +package gin + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/rs/cors" +) + +func init() { + gin.SetMode(gin.ReleaseMode) +} + +func TestAllowAllNotNil(t *testing.T) { + handler := AllowAll() + if handler == nil { + t.Error("Should not return nil Gin handler") + } +} + +func TestDefaultNotNil(t *testing.T) { + handler := Default() + if handler == nil { + t.Error("Should not return nil Gin handler") + } +} + +func TestNewNotNil(t *testing.T) { + handler := New(Options{}) + if handler == nil { + t.Error("Should not return nil Gin handler") + } +} + +func TestCorsWrapper_buildAbortsWhenPreflight(t *testing.T) { + res := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(res) + ctx.Request, _ = http.NewRequest("OPTIONS", "http://example.com/foo", nil) + ctx.Request.Header.Add("Origin", "http://example.com/") + ctx.Request.Header.Add("Access-Control-Request-Method", "POST") + ctx.Status(http.StatusAccepted) + res.Code = http.StatusAccepted + + handler := corsWrapper{Cors: cors.New(Options{ + // Intentionally left blank. + })}.build() + + handler(ctx) + + if !ctx.IsAborted() { + t.Error("Should abort on preflight requests") + } + if res.Code != http.StatusOK { + t.Error("Should abort with 200 OK status") + } +} + +func TestCorsWrapper_buildNotAbortsWhenPassthrough(t *testing.T) { + res := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(res) + ctx.Request, _ = http.NewRequest("OPTIONS", "http://example.com/foo", nil) + ctx.Request.Header.Add("Origin", "http://example.com/") + ctx.Request.Header.Add("Access-Control-Request-Method", "POST") + + handler := corsWrapper{cors.New(Options{ + OptionsPassthrough: true, + }), true}.build() + + handler(ctx) + + if ctx.IsAborted() { + t.Error("Should not abort when OPTIONS passthrough enabled") + } +} diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml deleted file mode 100644 index 20dd53b..0000000 --- a/vendor/github.com/satori/go.uuid/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: go -sudo: false -go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 - - tip -matrix: - allow_failures: - - go: tip - fast_finish: true -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -service=travis-ci -notifications: - email: false diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE deleted file mode 100644 index 926d549..0000000 --- a/vendor/github.com/satori/go.uuid/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013-2018 by Maxim Bublis - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md deleted file mode 100644 index 7b1a722..0000000 --- a/vendor/github.com/satori/go.uuid/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# UUID package for Go language - -[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) -[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) -[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) - -This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. - -With 100% test coverage and benchmarks out of box. - -Supported versions: -* Version 1, based on timestamp and MAC address (RFC 4122) -* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) -* Version 3, based on MD5 hashing (RFC 4122) -* Version 4, based on random numbers (RFC 4122) -* Version 5, based on SHA-1 hashing (RFC 4122) - -## Installation - -Use the `go` command: - - $ go get github.com/satori/go.uuid - -## Requirements - -UUID package requires Go >= 1.2. - -## Example - -```go -package main - -import ( - "fmt" - "github.com/satori/go.uuid" -) - -func main() { - // Creating UUID Version 4 - u1 := uuid.NewV4() - fmt.Printf("UUIDv4: %s\n", u1) - - // Parsing UUID from string input - u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - if err != nil { - fmt.Printf("Something gone wrong: %s", err) - } - fmt.Printf("Successfully parsed: %s", u2) -} -``` - -## Documentation - -[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. - -## Links -* [RFC 4122](http://tools.ietf.org/html/rfc4122) -* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) - -## Copyright - -Copyright (C) 2013-2018 by Maxim Bublis . - -UUID package released under MIT License. -See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/codec.go b/vendor/github.com/satori/go.uuid/codec.go deleted file mode 100644 index 656892c..0000000 --- a/vendor/github.com/satori/go.uuid/codec.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - "encoding/hex" - "fmt" -) - -// FromBytes returns UUID converted from raw byte slice input. -// It will return error if the slice isn't 16 bytes long. -func FromBytes(input []byte) (u UUID, err error) { - err = u.UnmarshalBinary(input) - return -} - -// FromBytesOrNil returns UUID converted from raw byte slice input. -// Same behavior as FromBytes, but returns a Nil UUID on error. -func FromBytesOrNil(input []byte) UUID { - uuid, err := FromBytes(input) - if err != nil { - return Nil - } - return uuid -} - -// FromString returns UUID parsed from string input. -// Input is expected in a form accepted by UnmarshalText. -func FromString(input string) (u UUID, err error) { - err = u.UnmarshalText([]byte(input)) - return -} - -// FromStringOrNil returns UUID parsed from string input. -// Same behavior as FromString, but returns a Nil UUID on error. -func FromStringOrNil(input string) UUID { - uuid, err := FromString(input) - if err != nil { - return Nil - } - return uuid -} - -// MarshalText implements the encoding.TextMarshaler interface. -// The encoding is the same as returned by String. -func (u UUID) MarshalText() (text []byte, err error) { - text = []byte(u.String()) - return -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Following formats are supported: -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", -// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", -// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" -// "6ba7b8109dad11d180b400c04fd430c8" -// ABNF for supported UUID text representation follows: -// uuid := canonical | hashlike | braced | urn -// plain := canonical | hashlike -// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct -// hashlike := 12hexoct -// braced := '{' plain '}' -// urn := URN ':' UUID-NID ':' plain -// URN := 'urn' -// UUID-NID := 'uuid' -// 12hexoct := 6hexoct 6hexoct -// 6hexoct := 4hexoct 2hexoct -// 4hexoct := 2hexoct 2hexoct -// 2hexoct := hexoct hexoct -// hexoct := hexdig hexdig -// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | -// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | -// 'A' | 'B' | 'C' | 'D' | 'E' | 'F' -func (u *UUID) UnmarshalText(text []byte) (err error) { - switch len(text) { - case 32: - return u.decodeHashLike(text) - case 36: - return u.decodeCanonical(text) - case 38: - return u.decodeBraced(text) - case 41: - fallthrough - case 45: - return u.decodeURN(text) - default: - return fmt.Errorf("uuid: incorrect UUID length: %s", text) - } -} - -// decodeCanonical decodes UUID string in format -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8". -func (u *UUID) decodeCanonical(t []byte) (err error) { - if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' { - return fmt.Errorf("uuid: incorrect UUID format %s", t) - } - - src := t[:] - dst := u[:] - - for i, byteGroup := range byteGroups { - if i > 0 { - src = src[1:] // skip dash - } - _, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup]) - if err != nil { - return - } - src = src[byteGroup:] - dst = dst[byteGroup/2:] - } - - return -} - -// decodeHashLike decodes UUID string in format -// "6ba7b8109dad11d180b400c04fd430c8". -func (u *UUID) decodeHashLike(t []byte) (err error) { - src := t[:] - dst := u[:] - - if _, err = hex.Decode(dst, src); err != nil { - return err - } - return -} - -// decodeBraced decodes UUID string in format -// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format -// "{6ba7b8109dad11d180b400c04fd430c8}". -func (u *UUID) decodeBraced(t []byte) (err error) { - l := len(t) - - if t[0] != '{' || t[l-1] != '}' { - return fmt.Errorf("uuid: incorrect UUID format %s", t) - } - - return u.decodePlain(t[1 : l-1]) -} - -// decodeURN decodes UUID string in format -// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format -// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8". -func (u *UUID) decodeURN(t []byte) (err error) { - total := len(t) - - urn_uuid_prefix := t[:9] - - if !bytes.Equal(urn_uuid_prefix, urnPrefix) { - return fmt.Errorf("uuid: incorrect UUID format: %s", t) - } - - return u.decodePlain(t[9:total]) -} - -// decodePlain decodes UUID string in canonical format -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format -// "6ba7b8109dad11d180b400c04fd430c8". -func (u *UUID) decodePlain(t []byte) (err error) { - switch len(t) { - case 32: - return u.decodeHashLike(t) - case 36: - return u.decodeCanonical(t) - default: - return fmt.Errorf("uuid: incorrrect UUID length: %s", t) - } -} - -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (u UUID) MarshalBinary() (data []byte, err error) { - data = u.Bytes() - return -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -// It will return error if the slice isn't 16 bytes long. -func (u *UUID) UnmarshalBinary(data []byte) (err error) { - if len(data) != Size { - err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) - return - } - copy(u[:], data) - - return -} diff --git a/vendor/github.com/satori/go.uuid/codec_test.go b/vendor/github.com/satori/go.uuid/codec_test.go deleted file mode 100644 index 101ec52..0000000 --- a/vendor/github.com/satori/go.uuid/codec_test.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - - . "gopkg.in/check.v1" -) - -type codecTestSuite struct{} - -var _ = Suite(&codecTestSuite{}) - -func (s *codecTestSuite) TestFromBytes(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1, err := FromBytes(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte{} - _, err = FromBytes(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) BenchmarkFromBytes(c *C) { - bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - for i := 0; i < c.N; i++ { - FromBytes(bytes) - } -} - -func (s *codecTestSuite) TestMarshalBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - b2, err := u.MarshalBinary() - c.Assert(err, IsNil) - c.Assert(bytes.Equal(b1, b2), Equals, true) -} - -func (s *codecTestSuite) BenchmarkMarshalBinary(c *C) { - u := NewV4() - for i := 0; i < c.N; i++ { - u.MarshalBinary() - } -} - -func (s *codecTestSuite) TestUnmarshalBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.UnmarshalBinary(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte{} - u2 := UUID{} - err = u2.UnmarshalBinary(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) TestFromString(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - s4 := "6ba7b8109dad11d180b400c04fd430c8" - s5 := "urn:uuid:6ba7b8109dad11d180b400c04fd430c8" - - _, err := FromString("") - c.Assert(err, NotNil) - - u1, err := FromString(s1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - u2, err := FromString(s2) - c.Assert(err, IsNil) - c.Assert(u2, Equals, u) - - u3, err := FromString(s3) - c.Assert(err, IsNil) - c.Assert(u3, Equals, u) - - u4, err := FromString(s4) - c.Assert(err, IsNil) - c.Assert(u4, Equals, u) - - u5, err := FromString(s5) - c.Assert(err, IsNil) - c.Assert(u5, Equals, u) -} - -func (s *codecTestSuite) BenchmarkFromString(c *C) { - str := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) BenchmarkFromStringUrn(c *C) { - str := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) BenchmarkFromStringWithBrackets(c *C) { - str := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) TestFromStringShort(c *C) { - // Invalid 35-character UUID string - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" - - for i := len(s1); i >= 0; i-- { - _, err := FromString(s1[:i]) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringLong(c *C) { - // Invalid 37+ character UUID string - strings := []string{ - "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", - "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", - "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", - } - - for _, str := range strings { - _, err := FromString(str) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringInvalid(c *C) { - // Invalid UUID string formats - strings := []string{ - "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", - "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8", - "uuid:urn:6ba7b8109dad11d180b400c04fd430c8", - "6ba7b8109-dad-11d1-80b4-00c04fd430c8", - "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", - "6ba7b810-9dad-11d18-0b4-00c04fd430c8", - "6ba7b810-9dad-11d1-80b40-0c04fd430c8", - "6ba7b810+9dad+11d1+80b4+00c04fd430c8", - "(6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "{6ba7b810-9dad-11d1-80b4-00c04fd430c8>", - "zba7b810-9dad-11d1-80b4-00c04fd430c8", - "6ba7b810-9dad11d180b400c04fd430c8", - "6ba7b8109dad-11d180b400c04fd430c8", - "6ba7b8109dad11d1-80b400c04fd430c8", - "6ba7b8109dad11d180b4-00c04fd430c8", - } - - for _, str := range strings { - _, err := FromString(str) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringOrNil(c *C) { - u := FromStringOrNil("") - c.Assert(u, Equals, Nil) -} - -func (s *codecTestSuite) TestFromBytesOrNil(c *C) { - b := []byte{} - u := FromBytesOrNil(b) - c.Assert(u, Equals, Nil) -} - -func (s *codecTestSuite) TestMarshalText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - b2, err := u.MarshalText() - c.Assert(err, IsNil) - c.Assert(bytes.Equal(b1, b2), Equals, true) -} - -func (s *codecTestSuite) BenchmarkMarshalText(c *C) { - u := NewV4() - for i := 0; i < c.N; i++ { - u.MarshalText() - } -} - -func (s *codecTestSuite) TestUnmarshalText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.UnmarshalText(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte("") - u2 := UUID{} - err = u2.UnmarshalText(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) BenchmarkUnmarshalText(c *C) { - bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - u := UUID{} - for i := 0; i < c.N; i++ { - u.UnmarshalText(bytes) - } -} - -var sink string - -func (s *codecTestSuite) BenchmarkMarshalToString(c *C) { - u := NewV4() - for i := 0; i < c.N; i++ { - sink = u.String() - } -} diff --git a/vendor/github.com/satori/go.uuid/generator.go b/vendor/github.com/satori/go.uuid/generator.go deleted file mode 100644 index 3f2f1da..0000000 --- a/vendor/github.com/satori/go.uuid/generator.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "crypto/md5" - "crypto/rand" - "crypto/sha1" - "encoding/binary" - "hash" - "net" - "os" - "sync" - "time" -) - -// Difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). -const epochStart = 122192928000000000 - -var ( - global = newDefaultGenerator() - - epochFunc = unixTimeFunc - posixUID = uint32(os.Getuid()) - posixGID = uint32(os.Getgid()) -) - -// NewV1 returns UUID based on current timestamp and MAC address. -func NewV1() UUID { - return global.NewV1() -} - -// NewV2 returns DCE Security UUID based on POSIX UID/GID. -func NewV2(domain byte) UUID { - return global.NewV2(domain) -} - -// NewV3 returns UUID based on MD5 hash of namespace UUID and name. -func NewV3(ns UUID, name string) UUID { - return global.NewV3(ns, name) -} - -// NewV4 returns random generated UUID. -func NewV4() UUID { - return global.NewV4() -} - -// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. -func NewV5(ns UUID, name string) UUID { - return global.NewV5(ns, name) -} - -// Generator provides interface for generating UUIDs. -type Generator interface { - NewV1() UUID - NewV2(domain byte) UUID - NewV3(ns UUID, name string) UUID - NewV4() UUID - NewV5(ns UUID, name string) UUID -} - -// Default generator implementation. -type generator struct { - storageOnce sync.Once - storageMutex sync.Mutex - - lastTime uint64 - clockSequence uint16 - hardwareAddr [6]byte -} - -func newDefaultGenerator() Generator { - return &generator{} -} - -// NewV1 returns UUID based on current timestamp and MAC address. -func (g *generator) NewV1() UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := g.getStorage() - - binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - - copy(u[10:], hardwareAddr) - - u.SetVersion(V1) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV2 returns DCE Security UUID based on POSIX UID/GID. -func (g *generator) NewV2(domain byte) UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := g.getStorage() - - switch domain { - case DomainPerson: - binary.BigEndian.PutUint32(u[0:], posixUID) - case DomainGroup: - binary.BigEndian.PutUint32(u[0:], posixGID) - } - - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - u[9] = domain - - copy(u[10:], hardwareAddr) - - u.SetVersion(V2) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV3 returns UUID based on MD5 hash of namespace UUID and name. -func (g *generator) NewV3(ns UUID, name string) UUID { - u := newFromHash(md5.New(), ns, name) - u.SetVersion(V3) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV4 returns random generated UUID. -func (g *generator) NewV4() UUID { - u := UUID{} - g.safeRandom(u[:]) - u.SetVersion(V4) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. -func (g *generator) NewV5(ns UUID, name string) UUID { - u := newFromHash(sha1.New(), ns, name) - u.SetVersion(V5) - u.SetVariant(VariantRFC4122) - - return u -} - -func (g *generator) initStorage() { - g.initClockSequence() - g.initHardwareAddr() -} - -func (g *generator) initClockSequence() { - buf := make([]byte, 2) - g.safeRandom(buf) - g.clockSequence = binary.BigEndian.Uint16(buf) -} - -func (g *generator) initHardwareAddr() { - interfaces, err := net.Interfaces() - if err == nil { - for _, iface := range interfaces { - if len(iface.HardwareAddr) >= 6 { - copy(g.hardwareAddr[:], iface.HardwareAddr) - return - } - } - } - - // Initialize hardwareAddr randomly in case - // of real network interfaces absence - g.safeRandom(g.hardwareAddr[:]) - - // Set multicast bit as recommended in RFC 4122 - g.hardwareAddr[0] |= 0x01 -} - -func (g *generator) safeRandom(dest []byte) { - if _, err := rand.Read(dest); err != nil { - panic(err) - } -} - -// Returns UUID v1/v2 storage state. -// Returns epoch timestamp, clock sequence, and hardware address. -func (g *generator) getStorage() (uint64, uint16, []byte) { - g.storageOnce.Do(g.initStorage) - - g.storageMutex.Lock() - defer g.storageMutex.Unlock() - - timeNow := epochFunc() - // Clock changed backwards since last UUID generation. - // Should increase clock sequence. - if timeNow <= g.lastTime { - g.clockSequence++ - } - g.lastTime = timeNow - - return timeNow, g.clockSequence, g.hardwareAddr[:] -} - -// Returns difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and current time. -// This is default epoch calculation function. -func unixTimeFunc() uint64 { - return epochStart + uint64(time.Now().UnixNano()/100) -} - -// Returns UUID based on hashing of namespace UUID and name. -func newFromHash(h hash.Hash, ns UUID, name string) UUID { - u := UUID{} - h.Write(ns[:]) - h.Write([]byte(name)) - copy(u[:], h.Sum(nil)) - - return u -} diff --git a/vendor/github.com/satori/go.uuid/generator_test.go b/vendor/github.com/satori/go.uuid/generator_test.go deleted file mode 100644 index cd69e2e..0000000 --- a/vendor/github.com/satori/go.uuid/generator_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - . "gopkg.in/check.v1" -) - -type genTestSuite struct{} - -var _ = Suite(&genTestSuite{}) - -func (s *genTestSuite) TestNewV1(c *C) { - u := NewV1() - c.Assert(u.Version(), Equals, V1) - c.Assert(u.Variant(), Equals, VariantRFC4122) - - u1 := NewV1() - u2 := NewV1() - c.Assert(u1, Not(Equals), u2) - - oldFunc := epochFunc - epochFunc = func() uint64 { return 0 } - - u3 := NewV1() - u4 := NewV1() - c.Assert(u3, Not(Equals), u4) - - epochFunc = oldFunc -} - -func (s *genTestSuite) BenchmarkNewV1(c *C) { - for i := 0; i < c.N; i++ { - NewV1() - } -} - -func (s *genTestSuite) TestNewV2(c *C) { - u1 := NewV2(DomainPerson) - c.Assert(u1.Version(), Equals, V2) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - - u2 := NewV2(DomainGroup) - c.Assert(u2.Version(), Equals, V2) - c.Assert(u2.Variant(), Equals, VariantRFC4122) -} - -func (s *genTestSuite) BenchmarkNewV2(c *C) { - for i := 0; i < c.N; i++ { - NewV2(DomainPerson) - } -} - -func (s *genTestSuite) TestNewV3(c *C) { - u := NewV3(NamespaceDNS, "www.example.com") - c.Assert(u.Version(), Equals, V3) - c.Assert(u.Variant(), Equals, VariantRFC4122) - c.Assert(u.String(), Equals, "5df41881-3aed-3515-88a7-2f4a814cf09e") - - u = NewV3(NamespaceDNS, "python.org") - c.Assert(u.String(), Equals, "6fa459ea-ee8a-3ca4-894e-db77e160355e") - - u1 := NewV3(NamespaceDNS, "golang.org") - u2 := NewV3(NamespaceDNS, "golang.org") - c.Assert(u1, Equals, u2) - - u3 := NewV3(NamespaceDNS, "example.com") - c.Assert(u1, Not(Equals), u3) - - u4 := NewV3(NamespaceURL, "golang.org") - c.Assert(u1, Not(Equals), u4) -} - -func (s *genTestSuite) BenchmarkNewV3(c *C) { - for i := 0; i < c.N; i++ { - NewV3(NamespaceDNS, "www.example.com") - } -} - -func (s *genTestSuite) TestNewV4(c *C) { - u := NewV4() - c.Assert(u.Version(), Equals, V4) - c.Assert(u.Variant(), Equals, VariantRFC4122) -} - -func (s *genTestSuite) BenchmarkNewV4(c *C) { - for i := 0; i < c.N; i++ { - NewV4() - } -} - -func (s *genTestSuite) TestNewV5(c *C) { - u := NewV5(NamespaceDNS, "www.example.com") - c.Assert(u.Version(), Equals, V5) - c.Assert(u.Variant(), Equals, VariantRFC4122) - - u = NewV5(NamespaceDNS, "python.org") - c.Assert(u.String(), Equals, "886313e1-3b8a-5372-9b90-0c9aee199e5d") - - u1 := NewV5(NamespaceDNS, "golang.org") - u2 := NewV5(NamespaceDNS, "golang.org") - c.Assert(u1, Equals, u2) - - u3 := NewV5(NamespaceDNS, "example.com") - c.Assert(u1, Not(Equals), u3) - - u4 := NewV5(NamespaceURL, "golang.org") - c.Assert(u1, Not(Equals), u4) -} - -func (s *genTestSuite) BenchmarkNewV5(c *C) { - for i := 0; i < c.N; i++ { - NewV5(NamespaceDNS, "www.example.com") - } -} diff --git a/vendor/github.com/satori/go.uuid/sql.go b/vendor/github.com/satori/go.uuid/sql.go deleted file mode 100644 index 56759d3..0000000 --- a/vendor/github.com/satori/go.uuid/sql.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "database/sql/driver" - "fmt" -) - -// Value implements the driver.Valuer interface. -func (u UUID) Value() (driver.Value, error) { - return u.String(), nil -} - -// Scan implements the sql.Scanner interface. -// A 16-byte slice is handled by UnmarshalBinary, while -// a longer byte slice or a string is handled by UnmarshalText. -func (u *UUID) Scan(src interface{}) error { - switch src := src.(type) { - case []byte: - if len(src) == Size { - return u.UnmarshalBinary(src) - } - return u.UnmarshalText(src) - - case string: - return u.UnmarshalText([]byte(src)) - } - - return fmt.Errorf("uuid: cannot convert %T to UUID", src) -} - -// NullUUID can be used with the standard sql package to represent a -// UUID value that can be NULL in the database -type NullUUID struct { - UUID UUID - Valid bool -} - -// Value implements the driver.Valuer interface. -func (u NullUUID) Value() (driver.Value, error) { - if !u.Valid { - return nil, nil - } - // Delegate to UUID Value function - return u.UUID.Value() -} - -// Scan implements the sql.Scanner interface. -func (u *NullUUID) Scan(src interface{}) error { - if src == nil { - u.UUID, u.Valid = Nil, false - return nil - } - - // Delegate to UUID Scan function - u.Valid = true - return u.UUID.Scan(src) -} diff --git a/vendor/github.com/satori/go.uuid/sql_test.go b/vendor/github.com/satori/go.uuid/sql_test.go deleted file mode 100644 index 74255f5..0000000 --- a/vendor/github.com/satori/go.uuid/sql_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - . "gopkg.in/check.v1" -) - -type sqlTestSuite struct{} - -var _ = Suite(&sqlTestSuite{}) - -func (s *sqlTestSuite) TestValue(c *C) { - u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - c.Assert(err, IsNil) - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, Equals, u.String()) -} - -func (s *sqlTestSuite) TestValueNil(c *C) { - u := UUID{} - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, Equals, Nil.String()) -} - -func (s *sqlTestSuite) TestNullUUIDValueNil(c *C) { - u := NullUUID{} - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, IsNil) -} - -func (s *sqlTestSuite) TestScanBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.Scan(b1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - b2 := []byte{} - u2 := UUID{} - - err = u2.Scan(b2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanString(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := UUID{} - err := u1.Scan(s1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - s2 := "" - u2 := UUID{} - - err = u2.Scan(s2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.Scan(b1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - b2 := []byte("") - u2 := UUID{} - err = u2.Scan(b2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanUnsupported(c *C) { - u := UUID{} - - err := u.Scan(true) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanNil(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - err := u.Scan(nil) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestNullUUIDScanValid(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := NullUUID{} - err := u1.Scan(s1) - c.Assert(err, IsNil) - c.Assert(u1.Valid, Equals, true) - c.Assert(u1.UUID, Equals, u) -} - -func (s *sqlTestSuite) TestNullUUIDScanNil(c *C) { - u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} - - err := u.Scan(nil) - c.Assert(err, IsNil) - c.Assert(u.Valid, Equals, false) - c.Assert(u.UUID, Equals, Nil) -} diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go deleted file mode 100644 index a2b8e2c..0000000 --- a/vendor/github.com/satori/go.uuid/uuid.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Package uuid provides implementation of Universally Unique Identifier (UUID). -// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and -// version 2 (as specified in DCE 1.1). -package uuid - -import ( - "bytes" - "encoding/hex" -) - -// Size of a UUID in bytes. -const Size = 16 - -// UUID representation compliant with specification -// described in RFC 4122. -type UUID [Size]byte - -// UUID versions -const ( - _ byte = iota - V1 - V2 - V3 - V4 - V5 -) - -// UUID layout variants. -const ( - VariantNCS byte = iota - VariantRFC4122 - VariantMicrosoft - VariantFuture -) - -// UUID DCE domains. -const ( - DomainPerson = iota - DomainGroup - DomainOrg -) - -// String parse helpers. -var ( - urnPrefix = []byte("urn:uuid:") - byteGroups = []int{8, 4, 4, 4, 12} -) - -// Nil is special form of UUID that is specified to have all -// 128 bits set to zero. -var Nil = UUID{} - -// Predefined namespace UUIDs. -var ( - NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) - NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) - NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) - NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) -) - -// Equal returns true if u1 and u2 equals, otherwise returns false. -func Equal(u1 UUID, u2 UUID) bool { - return bytes.Equal(u1[:], u2[:]) -} - -// Version returns algorithm version used to generate UUID. -func (u UUID) Version() byte { - return u[6] >> 4 -} - -// Variant returns UUID layout variant. -func (u UUID) Variant() byte { - switch { - case (u[8] >> 7) == 0x00: - return VariantNCS - case (u[8] >> 6) == 0x02: - return VariantRFC4122 - case (u[8] >> 5) == 0x06: - return VariantMicrosoft - case (u[8] >> 5) == 0x07: - fallthrough - default: - return VariantFuture - } -} - -// Bytes returns bytes slice representation of UUID. -func (u UUID) Bytes() []byte { - return u[:] -} - -// Returns canonical string representation of UUID: -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. -func (u UUID) String() string { - buf := make([]byte, 36) - - hex.Encode(buf[0:8], u[0:4]) - buf[8] = '-' - hex.Encode(buf[9:13], u[4:6]) - buf[13] = '-' - hex.Encode(buf[14:18], u[6:8]) - buf[18] = '-' - hex.Encode(buf[19:23], u[8:10]) - buf[23] = '-' - hex.Encode(buf[24:], u[10:]) - - return string(buf) -} - -// SetVersion sets version bits. -func (u *UUID) SetVersion(v byte) { - u[6] = (u[6] & 0x0f) | (v << 4) -} - -// SetVariant sets variant bits. -func (u *UUID) SetVariant(v byte) { - switch v { - case VariantNCS: - u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) - case VariantRFC4122: - u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) - case VariantMicrosoft: - u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) - case VariantFuture: - fallthrough - default: - u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) - } -} - -// Must is a helper that wraps a call to a function returning (UUID, error) -// and panics if the error is non-nil. It is intended for use in variable -// initializations such as -// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")); -func Must(u UUID, err error) UUID { - if err != nil { - panic(err) - } - return u -} diff --git a/vendor/github.com/satori/go.uuid/uuid_test.go b/vendor/github.com/satori/go.uuid/uuid_test.go deleted file mode 100644 index beb336d..0000000 --- a/vendor/github.com/satori/go.uuid/uuid_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - "testing" - - . "gopkg.in/check.v1" -) - -// Hook up gocheck into the "go test" runner. -func TestUUID(t *testing.T) { TestingT(t) } - -type testSuite struct{} - -var _ = Suite(&testSuite{}) - -func (s *testSuite) TestBytes(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - c.Assert(bytes.Equal(u.Bytes(), bytes1), Equals, true) -} - -func (s *testSuite) TestString(c *C) { - c.Assert(NamespaceDNS.String(), Equals, "6ba7b810-9dad-11d1-80b4-00c04fd430c8") -} - -func (s *testSuite) TestEqual(c *C) { - c.Assert(Equal(NamespaceDNS, NamespaceDNS), Equals, true) - c.Assert(Equal(NamespaceDNS, NamespaceURL), Equals, false) -} - -func (s *testSuite) TestVersion(c *C) { - u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u.Version(), Equals, V1) -} - -func (s *testSuite) TestSetVersion(c *C) { - u := UUID{} - u.SetVersion(4) - c.Assert(u.Version(), Equals, V4) -} - -func (s *testSuite) TestVariant(c *C) { - u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u1.Variant(), Equals, VariantNCS) - - u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u2.Variant(), Equals, VariantRFC4122) - - u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u3.Variant(), Equals, VariantMicrosoft) - - u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u4.Variant(), Equals, VariantFuture) -} - -func (s *testSuite) TestSetVariant(c *C) { - u := UUID{} - u.SetVariant(VariantNCS) - c.Assert(u.Variant(), Equals, VariantNCS) - u.SetVariant(VariantRFC4122) - c.Assert(u.Variant(), Equals, VariantRFC4122) - u.SetVariant(VariantMicrosoft) - c.Assert(u.Variant(), Equals, VariantMicrosoft) - u.SetVariant(VariantFuture) - c.Assert(u.Variant(), Equals, VariantFuture) -} diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml index a23296a..2f19b4a 100644 --- a/vendor/github.com/sirupsen/logrus/.travis.yml +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -1,9 +1,7 @@ language: go go: - - 1.6.x - - 1.7.x - - 1.8.x - - tip + - 1.9.x + - 1.10.x env: - GOMAXPROCS=4 GORACE=halt_on_error=1 install: diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index cc58f64..1bd1deb 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,8 @@ +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + # 1.0.4 * Fix race when adding hooks (#612) diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md index 08584b5..072e99b 100644 --- a/vendor/github.com/sirupsen/logrus/README.md +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -220,7 +220,7 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in ```go import ( log "github.com/sirupsen/logrus" - "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" "log/syslog" ) @@ -241,58 +241,8 @@ func init() { ``` Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). -| Hook | Description | -| ----- | ----------- | -| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. | -| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | -| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) | -| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) | -| [AzureTableHook](https://github.com/kpfaulkner/azuretablehook/) | Hook for logging to Azure Table Storage| -| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | -| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | -| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) | -| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch| -| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/) -| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | -| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) | -| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | -| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | -| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | -| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | -| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) | -| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | -| [KafkaLogrus](https://github.com/tracer0tong/kafkalogrus) | Hook for logging to Kafka | -| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | -| [Logbeat](https://github.com/macandmia/logbeat) | Hook for logging to [Opbeat](https://opbeat.com/) | -| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) | -| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) | -| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) | -| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | -| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) | -| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | -| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) | -| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | -| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) | -| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | -| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | -| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) | -| [Promrus](https://github.com/weaveworks/promrus) | Expose number of log messages as [Prometheus](https://prometheus.io/) metrics | -| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) | -| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | -| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) | -| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | -| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)| -| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | -| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | -| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) | -| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)| -| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | -| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. | -| [Telegram](https://github.com/rossmcdonald/telegram_hook) | Hook for logging errors to [Telegram](https://telegram.org/) | -| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) | -| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) | -| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash | -| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) | +A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) + #### Level logging @@ -370,6 +320,8 @@ The built-in logging formatters are: field to `true`. To force no colored output even if there is a TTY set the `DisableColors` field to `true`. For Windows, see [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * When colors are enabled, levels are truncated to 4 characters by default. To disable + truncation set the `DisableLevelTruncation` field to `true`. * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). * `logrus.JSONFormatter`. Logs fields as JSON. * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). @@ -493,7 +445,7 @@ logrus.RegisterExitHandler(handler) #### Thread safety -By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs. +By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs. If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. Situation when locking is not needed includes: diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go index 1fad45e..473bd1a 100644 --- a/vendor/github.com/sirupsen/logrus/entry.go +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -48,7 +48,7 @@ type Entry struct { func NewEntry(logger *Logger) *Entry { return &Entry{ Logger: logger, - // Default is three fields, give a little extra room + // Default is five fields, give a little extra room Data: make(Fields, 5), } } @@ -83,43 +83,41 @@ func (entry *Entry) WithFields(fields Fields) *Entry { for k, v := range fields { data[k] = v } - return &Entry{Logger: entry.Logger, Data: data} + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time} +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t} } // This function is not declared with a pointer value because otherwise // race conditions will occur when using multiple goroutines func (entry Entry) log(level Level, msg string) { var buffer *bytes.Buffer - entry.Time = time.Now() + + // Default to now, but allow users to override if they want. + // + // We don't have to worry about polluting future calls to Entry#log() + // with this assignment because this function is declared with a + // non-pointer receiver. + if entry.Time.IsZero() { + entry.Time = time.Now() + } + entry.Level = level entry.Message = msg - entry.Logger.mu.Lock() - err := entry.Logger.Hooks.Fire(level, &entry) - entry.Logger.mu.Unlock() - if err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) - entry.Logger.mu.Unlock() - } + entry.fireHooks() + buffer = bufferPool.Get().(*bytes.Buffer) buffer.Reset() defer bufferPool.Put(buffer) entry.Buffer = buffer - serialized, err := entry.Logger.Formatter.Format(&entry) + + entry.write() + entry.Buffer = nil - if err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) - entry.Logger.mu.Unlock() - } else { - entry.Logger.mu.Lock() - _, err = entry.Logger.Out.Write(serialized) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) - } - entry.Logger.mu.Unlock() - } // To avoid Entry#log() returning a value that only would make sense for // panic() to use in Entry#Panic(), we avoid the allocation by checking @@ -129,6 +127,29 @@ func (entry Entry) log(level Level, msg string) { } } +func (entry *Entry) fireHooks() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + err := entry.Logger.Hooks.Fire(entry.Level, entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + serialized, err := entry.Logger.Formatter.Format(entry) + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + } else { + _, err = entry.Logger.Out.Write(serialized) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + } + } +} + func (entry *Entry) Debug(args ...interface{}) { if entry.Logger.level() >= DebugLevel { entry.log(DebugLevel, fmt.Sprint(args...)) diff --git a/vendor/github.com/sirupsen/logrus/entry_test.go b/vendor/github.com/sirupsen/logrus/entry_test.go index 99c3b41..a81e2b3 100644 --- a/vendor/github.com/sirupsen/logrus/entry_test.go +++ b/vendor/github.com/sirupsen/logrus/entry_test.go @@ -75,3 +75,41 @@ func TestEntryPanicf(t *testing.T) { entry := NewEntry(logger) entry.WithField("err", errBoom).Panicf("kaboom %v", true) } + +const ( + badMessage = "this is going to panic" + panicMessage = "this is broken" +) + +type panickyHook struct{} + +func (p *panickyHook) Levels() []Level { + return []Level{InfoLevel} +} + +func (p *panickyHook) Fire(entry *Entry) error { + if entry.Message == badMessage { + panic(panicMessage) + } + + return nil +} + +func TestEntryHooksPanic(t *testing.T) { + logger := New() + logger.Out = &bytes.Buffer{} + logger.Level = InfoLevel + logger.Hooks.Add(&panickyHook{}) + + defer func() { + p := recover() + assert.NotNil(t, p) + assert.Equal(t, panicMessage, p) + + entry := NewEntry(logger) + entry.Info("another message") + }() + + entry := NewEntry(logger) + entry.Info(badMessage) +} diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go index 013183e..eb612a6 100644 --- a/vendor/github.com/sirupsen/logrus/exported.go +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -2,6 +2,7 @@ package logrus import ( "io" + "time" ) var ( @@ -15,9 +16,7 @@ func StandardLogger() *Logger { // SetOutput sets the standard logger output. func SetOutput(out io.Writer) { - std.mu.Lock() - defer std.mu.Unlock() - std.Out = out + std.SetOutput(out) } // SetFormatter sets the standard logger formatter. @@ -72,6 +71,15 @@ func WithFields(fields Fields) *Entry { return std.WithFields(fields) } +// WithTime creats an entry from the standard logger and overrides the time of +// logs generated with it. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithTime(t time.Time) *Entry { + return std.WithTime(t) +} + // Debug logs a message at level Debug on the standard logger. func Debug(args ...interface{}) { std.Debug(args...) @@ -107,7 +115,7 @@ func Panic(args ...interface{}) { std.Panic(args...) } -// Fatal logs a message at level Fatal on the standard logger. +// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1. func Fatal(args ...interface{}) { std.Fatal(args...) } @@ -147,7 +155,7 @@ func Panicf(format string, args ...interface{}) { std.Panicf(format, args...) } -// Fatalf logs a message at level Fatal on the standard logger. +// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1. func Fatalf(format string, args ...interface{}) { std.Fatalf(format, args...) } @@ -187,7 +195,7 @@ func Panicln(args ...interface{}) { std.Panicln(args...) } -// Fatalln logs a message at level Fatal on the standard logger. +// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1. func Fatalln(args ...interface{}) { std.Fatalln(args...) } diff --git a/vendor/github.com/sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go index b183ff5..83c7494 100644 --- a/vendor/github.com/sirupsen/logrus/formatter.go +++ b/vendor/github.com/sirupsen/logrus/formatter.go @@ -30,16 +30,22 @@ type Formatter interface { // // It's not exported because it's still using Data in an opinionated way. It's to // avoid code duplication between the two default formatters. -func prefixFieldClashes(data Fields) { - if t, ok := data["time"]; ok { - data["fields.time"] = t +func prefixFieldClashes(data Fields, fieldMap FieldMap) { + timeKey := fieldMap.resolve(FieldKeyTime) + if t, ok := data[timeKey]; ok { + data["fields."+timeKey] = t + delete(data, timeKey) } - if m, ok := data["msg"]; ok { - data["fields.msg"] = m + msgKey := fieldMap.resolve(FieldKeyMsg) + if m, ok := data[msgKey]; ok { + data["fields."+msgKey] = m + delete(data, msgKey) } - if l, ok := data["level"]; ok { - data["fields.level"] = l + levelKey := fieldMap.resolve(FieldKeyLevel) + if l, ok := data[levelKey]; ok { + data["fields."+levelKey] = l + delete(data, levelKey) } } diff --git a/vendor/github.com/sirupsen/logrus/hooks/test/test.go b/vendor/github.com/sirupsen/logrus/hooks/test/test.go index 62c4845..234a17d 100644 --- a/vendor/github.com/sirupsen/logrus/hooks/test/test.go +++ b/vendor/github.com/sirupsen/logrus/hooks/test/test.go @@ -15,7 +15,7 @@ type Hook struct { // Entries is an array of all entries that have been received by this hook. // For safe access, use the AllEntries() method, rather than reading this // value directly. - Entries []*logrus.Entry + Entries []logrus.Entry mu sync.RWMutex } @@ -52,7 +52,7 @@ func NewNullLogger() (*logrus.Logger, *Hook) { func (t *Hook) Fire(e *logrus.Entry) error { t.mu.Lock() defer t.mu.Unlock() - t.Entries = append(t.Entries, e) + t.Entries = append(t.Entries, *e) return nil } @@ -68,9 +68,7 @@ func (t *Hook) LastEntry() *logrus.Entry { if i < 0 { return nil } - // Make a copy, for safety - e := *t.Entries[i] - return &e + return &t.Entries[i] } // AllEntries returns all entries that were logged. @@ -79,10 +77,9 @@ func (t *Hook) AllEntries() []*logrus.Entry { defer t.mu.RUnlock() // Make a copy so the returned value won't race with future log requests entries := make([]*logrus.Entry, len(t.Entries)) - for i, entry := range t.Entries { + for i := 0; i < len(t.Entries); i++ { // Make a copy, for safety - e := *entry - entries[i] = &e + entries[i] = &t.Entries[i] } return entries } @@ -91,5 +88,5 @@ func (t *Hook) AllEntries() []*logrus.Entry { func (t *Hook) Reset() { t.mu.Lock() defer t.mu.Unlock() - t.Entries = make([]*logrus.Entry, 0) + t.Entries = make([]logrus.Entry, 0) } diff --git a/vendor/github.com/sirupsen/logrus/hooks/test/test_test.go b/vendor/github.com/sirupsen/logrus/hooks/test/test_test.go index 3f55cfe..d6f6d30 100644 --- a/vendor/github.com/sirupsen/logrus/hooks/test/test_test.go +++ b/vendor/github.com/sirupsen/logrus/hooks/test/test_test.go @@ -1,14 +1,16 @@ package test import ( + "math/rand" + "sync" "testing" + "time" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) func TestAllHooks(t *testing.T) { - assert := assert.New(t) logger, hook := NewNullLogger() @@ -35,5 +37,37 @@ func TestAllHooks(t *testing.T) { assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) assert.Equal("Hello error", hook.LastEntry().Message) assert.Equal(1, len(hook.Entries)) - +} + +func TestLoggingWithHooksRace(t *testing.T) { + + rand.Seed(time.Now().Unix()) + unlocker := rand.Int() % 100 + + assert := assert.New(t) + logger, hook := NewNullLogger() + + var wgOne, wgAll sync.WaitGroup + wgOne.Add(1) + wgAll.Add(100) + + for i := 0; i < 100; i++ { + go func(i int) { + logger.Info("info") + wgAll.Done() + if i == unlocker { + wgOne.Done() + } + }(i) + } + + wgOne.Wait() + + assert.Equal(logrus.InfoLevel, hook.LastEntry().Level) + assert.Equal("info", hook.LastEntry().Message) + + wgAll.Wait() + + entries := hook.AllEntries() + assert.Equal(100, len(entries)) } diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go index fb01c1b..dab1761 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -33,6 +33,9 @@ type JSONFormatter struct { // DisableTimestamp allows disabling automatic timestamps in output DisableTimestamp bool + // DataKey allows users to put all the log entry parameters into a nested dictionary at a given key. + DataKey string + // FieldMap allows users to customize the names of keys for default fields. // As an example: // formatter := &JSONFormatter{ @@ -58,7 +61,14 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { data[k] = v } } - prefixFieldClashes(data) + + if f.DataKey != "" { + newData := make(Fields, 4) + newData[f.DataKey] = data + data = newData + } + + prefixFieldClashes(data, f.FieldMap) timestampFormat := f.TimestampFormat if timestampFormat == "" { diff --git a/vendor/github.com/sirupsen/logrus/json_formatter_test.go b/vendor/github.com/sirupsen/logrus/json_formatter_test.go index 51093a7..0dde300 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter_test.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter_test.go @@ -3,6 +3,7 @@ package logrus import ( "encoding/json" "errors" + "fmt" "strings" "testing" ) @@ -106,6 +107,102 @@ func TestFieldClashWithLevel(t *testing.T) { } } +func TestFieldClashWithRemappedFields(t *testing.T) { + formatter := &JSONFormatter{ + FieldMap: FieldMap{ + FieldKeyTime: "@timestamp", + FieldKeyLevel: "@level", + FieldKeyMsg: "@message", + }, + } + + b, err := formatter.Format(WithFields(Fields{ + "@timestamp": "@timestamp", + "@level": "@level", + "@message": "@message", + "timestamp": "timestamp", + "level": "level", + "msg": "msg", + })) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + for _, field := range []string{"timestamp", "level", "msg"} { + if entry[field] != field { + t.Errorf("Expected field %v to be untouched; got %v", field, entry[field]) + } + + remappedKey := fmt.Sprintf("fields.%s", field) + if remapped, ok := entry[remappedKey]; ok { + t.Errorf("Expected %s to be empty; got %v", remappedKey, remapped) + } + } + + for _, field := range []string{"@timestamp", "@level", "@message"} { + if entry[field] == field { + t.Errorf("Expected field %v to be mapped to an Entry value", field) + } + + remappedKey := fmt.Sprintf("fields.%s", field) + if remapped, ok := entry[remappedKey]; ok { + if remapped != field { + t.Errorf("Expected field %v to be copied to %s; got %v", field, remappedKey, remapped) + } + } else { + t.Errorf("Expected field %v to be copied to %s; was absent", field, remappedKey) + } + } +} + +func TestFieldsInNestedDictionary(t *testing.T) { + formatter := &JSONFormatter{ + DataKey: "args", + } + + logEntry := WithFields(Fields{ + "level": "level", + "test": "test", + }) + logEntry.Level = InfoLevel + + b, err := formatter.Format(logEntry) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + args := entry["args"].(map[string]interface{}) + + for _, field := range []string{"test", "level"} { + if value, present := args[field]; !present || value != field { + t.Errorf("Expected field %v to be present under 'args'; untouched", field) + } + } + + for _, field := range []string{"test", "fields.level"} { + if _, present := entry[field]; present { + t.Errorf("Expected field %v not to be present at top level", field) + } + } + + // with nested object, "level" shouldn't clash + if entry["level"] != "info" { + t.Errorf("Expected 'level' field to contain 'info'") + } +} + func TestJSONEntryEndsWithNewline(t *testing.T) { formatter := &JSONFormatter{} diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index fdaf8a6..342f797 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -5,6 +5,7 @@ import ( "os" "sync" "sync/atomic" + "time" ) type Logger struct { @@ -88,7 +89,7 @@ func (logger *Logger) releaseEntry(entry *Entry) { } // Adds a field to the log entry, note that it doesn't log until you call -// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry. +// Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry. // If you want multiple fields, use `WithFields`. func (logger *Logger) WithField(key string, value interface{}) *Entry { entry := logger.newEntry() @@ -112,6 +113,13 @@ func (logger *Logger) WithError(err error) *Entry { return entry.WithError(err) } +// Overrides the time of the log entry. +func (logger *Logger) WithTime(t time.Time) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithTime(t) +} + func (logger *Logger) Debugf(format string, args ...interface{}) { if logger.level() >= DebugLevel { entry := logger.newEntry() @@ -316,6 +324,12 @@ func (logger *Logger) SetLevel(level Level) { atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) } +func (logger *Logger) SetOutput(out io.Writer) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Out = out +} + func (logger *Logger) AddHook(hook Hook) { logger.mu.Lock() defer logger.mu.Unlock() diff --git a/vendor/github.com/sirupsen/logrus/logrus_test.go b/vendor/github.com/sirupsen/logrus/logrus_test.go index 78cbc28..78e1301 100644 --- a/vendor/github.com/sirupsen/logrus/logrus_test.go +++ b/vendor/github.com/sirupsen/logrus/logrus_test.go @@ -7,6 +7,7 @@ import ( "strings" "sync" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -209,6 +210,65 @@ func TestDefaultFieldsAreNotPrefixed(t *testing.T) { }) } +func TestWithTimeShouldOverrideTime(t *testing.T) { + now := time.Now().Add(24 * time.Hour) + + LogAndAssertJSON(t, func(log *Logger) { + log.WithTime(now).Info("foobar") + }, func(fields Fields) { + assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat)) + }) +} + +func TestWithTimeShouldNotOverrideFields(t *testing.T) { + now := time.Now().Add(24 * time.Hour) + + LogAndAssertJSON(t, func(log *Logger) { + log.WithField("herp", "derp").WithTime(now).Info("blah") + }, func(fields Fields) { + assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat)) + assert.Equal(t, fields["herp"], "derp") + }) +} + +func TestWithFieldShouldNotOverrideTime(t *testing.T) { + now := time.Now().Add(24 * time.Hour) + + LogAndAssertJSON(t, func(log *Logger) { + log.WithTime(now).WithField("herp", "derp").Info("blah") + }, func(fields Fields) { + assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat)) + assert.Equal(t, fields["herp"], "derp") + }) +} + +func TestTimeOverrideMultipleLogs(t *testing.T) { + var buffer bytes.Buffer + var firstFields, secondFields Fields + + logger := New() + logger.Out = &buffer + formatter := new(JSONFormatter) + formatter.TimestampFormat = time.StampMilli + logger.Formatter = formatter + + llog := logger.WithField("herp", "derp") + llog.Info("foo") + + err := json.Unmarshal(buffer.Bytes(), &firstFields) + assert.NoError(t, err, "should have decoded first message") + + buffer.Reset() + + time.Sleep(10 * time.Millisecond) + llog.Info("bar") + + err = json.Unmarshal(buffer.Bytes(), &secondFields) + assert.NoError(t, err, "should have decoded second message") + + assert.NotEqual(t, firstFields["time"], secondFields["time"], "timestamps should not be equal") +} + func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) { var buffer bytes.Buffer diff --git a/vendor/github.com/sirupsen/logrus/terminal_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_bsd.go index d7b3893..4880d13 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_bsd.go +++ b/vendor/github.com/sirupsen/logrus/terminal_bsd.go @@ -1,5 +1,5 @@ // +build darwin freebsd openbsd netbsd dragonfly -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go index 2403de9..3de08e8 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go +++ b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go @@ -1,4 +1,4 @@ -// +build appengine +// +build appengine gopherjs package logrus diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go index 116bcb4..067047a 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go +++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go @@ -1,4 +1,4 @@ -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/vendor/github.com/sirupsen/logrus/terminal_linux.go b/vendor/github.com/sirupsen/logrus/terminal_linux.go index 88d7298..f29a009 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_linux.go +++ b/vendor/github.com/sirupsen/logrus/terminal_linux.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index 61b21ca..3e55040 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -20,6 +20,7 @@ const ( var ( baseTimestamp time.Time + emptyFieldMap FieldMap ) func init() { @@ -50,12 +51,24 @@ type TextFormatter struct { // be desired. DisableSorting bool + // Disables the truncation of the level text to 4 characters. + DisableLevelTruncation bool + // QuoteEmptyFields will wrap empty fields in quotes if true QuoteEmptyFields bool // Whether the logger's out is to a terminal isTerminal bool + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &TextFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message"}} + FieldMap FieldMap + sync.Once } @@ -67,7 +80,8 @@ func (f *TextFormatter) init(entry *Entry) { // Format renders a single log entry func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { - var b *bytes.Buffer + prefixFieldClashes(entry.Data, f.FieldMap) + keys := make([]string, 0, len(entry.Data)) for k := range entry.Data { keys = append(keys, k) @@ -76,14 +90,14 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { if !f.DisableSorting { sort.Strings(keys) } + + var b *bytes.Buffer if entry.Buffer != nil { b = entry.Buffer } else { b = &bytes.Buffer{} } - prefixFieldClashes(entry.Data) - f.Do(func() { f.init(entry) }) isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors @@ -96,11 +110,11 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { f.printColored(b, entry, keys, timestampFormat) } else { if !f.DisableTimestamp { - f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyTime), entry.Time.Format(timestampFormat)) } - f.appendKeyValue(b, "level", entry.Level.String()) + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyLevel), entry.Level.String()) if entry.Message != "" { - f.appendKeyValue(b, "msg", entry.Message) + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyMsg), entry.Message) } for _, key := range keys { f.appendKeyValue(b, key, entry.Data[key]) @@ -124,7 +138,10 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin levelColor = blue } - levelText := strings.ToUpper(entry.Level.String())[0:4] + levelText := strings.ToUpper(entry.Level.String()) + if !f.DisableLevelTruncation { + levelText = levelText[0:4] + } if f.DisableTimestamp { fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message) diff --git a/vendor/github.com/sirupsen/logrus/text_formatter_test.go b/vendor/github.com/sirupsen/logrus/text_formatter_test.go index d93b931..921d052 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter_test.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestFormatting(t *testing.T) { @@ -128,6 +130,44 @@ func TestTimestampFormat(t *testing.T) { checkTimeStr("") } +func TestDisableLevelTruncation(t *testing.T) { + entry := &Entry{ + Time: time.Now(), + Message: "testing", + } + keys := []string{} + timestampFormat := "Mon Jan 2 15:04:05 -0700 MST 2006" + checkDisableTruncation := func(disabled bool, level Level) { + tf := &TextFormatter{DisableLevelTruncation: disabled} + var b bytes.Buffer + entry.Level = level + tf.printColored(&b, entry, keys, timestampFormat) + logLine := (&b).String() + if disabled { + expected := strings.ToUpper(level.String()) + if !strings.Contains(logLine, expected) { + t.Errorf("level string expected to be %s when truncation disabled", expected) + } + } else { + expected := strings.ToUpper(level.String()) + if len(level.String()) > 4 { + if strings.Contains(logLine, expected) { + t.Errorf("level string %s expected to be truncated to %s when truncation is enabled", expected, expected[0:4]) + } + } else { + if !strings.Contains(logLine, expected) { + t.Errorf("level string expected to be %s when truncation is enabled and level string is below truncation threshold", expected) + } + } + } + } + + checkDisableTruncation(true, DebugLevel) + checkDisableTruncation(true, InfoLevel) + checkDisableTruncation(false, ErrorLevel) + checkDisableTruncation(false, InfoLevel) +} + func TestDisableTimestampWithColoredOutput(t *testing.T) { tf := &TextFormatter{DisableTimestamp: true, ForceColors: true} @@ -137,5 +177,44 @@ func TestDisableTimestampWithColoredOutput(t *testing.T) { } } +func TestTextFormatterFieldMap(t *testing.T) { + formatter := &TextFormatter{ + DisableColors: true, + FieldMap: FieldMap{ + FieldKeyMsg: "message", + FieldKeyLevel: "somelevel", + FieldKeyTime: "timeywimey", + }, + } + + entry := &Entry{ + Message: "oh hi", + Level: WarnLevel, + Time: time.Date(1981, time.February, 24, 4, 28, 3, 100, time.UTC), + Data: Fields{ + "field1": "f1", + "message": "messagefield", + "somelevel": "levelfield", + "timeywimey": "timeywimeyfield", + }, + } + + b, err := formatter.Format(entry) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + assert.Equal(t, + `timeywimey="1981-02-24T04:28:03Z" `+ + `somelevel=warning `+ + `message="oh hi" `+ + `field1=f1 `+ + `fields.message=messagefield `+ + `fields.somelevel=levelfield `+ + `fields.timeywimey=timeywimeyfield`+"\n", + string(b), + "Formatted output doesn't respect FieldMap") +} + // TODO add tests for sorting etc., this requires a parser for the text // formatter output. diff --git a/vendor/github.com/stretchr/testify/.travis.yml b/vendor/github.com/stretchr/testify/.travis.yml index b33dc9f..f408b4c 100644 --- a/vendor/github.com/stretchr/testify/.travis.yml +++ b/vendor/github.com/stretchr/testify/.travis.yml @@ -3,13 +3,13 @@ language: go sudo: false go: - - 1.7 - - 1.8 - - 1.9 + - "1.8" + - "1.9" + - "1.10" - tip script: - ./.travis.gogenerate.sh - ./.travis.gofmt.sh - ./.travis.govet.sh - - go test -v -race ./... + - go test -v -race $(go list ./... | grep -v vendor) diff --git a/vendor/github.com/stretchr/testify/Gopkg.lock b/vendor/github.com/stretchr/testify/Gopkg.lock index f52deee..294cda0 100644 --- a/vendor/github.com/stretchr/testify/Gopkg.lock +++ b/vendor/github.com/stretchr/testify/Gopkg.lock @@ -10,16 +10,18 @@ [[projects]] name = "github.com/pmezard/go-difflib" packages = ["difflib"] - revision = "d8ed2627bdf02c080bf22230dbb337003b7aba2d" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" [[projects]] name = "github.com/stretchr/objx" packages = ["."] - revision = "cbeaeb16a013161a98496fad62933b1d21786672" + revision = "facf9a85c22f48d2f52f2380e4efce1768749a89" + version = "v0.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "6bd8fb1f11a0d3df245fc01bd8853f6dac40b83457e780f7978ca30244647c7b" + inputs-digest = "448ddae4702c6aded2555faafd390c537789bb1c483f70b0431e6634f73f2090" solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/stretchr/testify/Gopkg.toml b/vendor/github.com/stretchr/testify/Gopkg.toml index dac8623..a16374c 100644 --- a/vendor/github.com/stretchr/testify/Gopkg.toml +++ b/vendor/github.com/stretchr/testify/Gopkg.toml @@ -1,26 +1,16 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - +[prune] + unused-packages = true + non-go = true + go-tests = true [[constraint]] name = "github.com/davecgh/go-spew" - version = ">=1.0.0, <=3.0.0-g6d21280" + version = "~1.1.0" + +[[constraint]] + name = "github.com/pmezard/go-difflib" + version = "~1.0.0" + +[[constraint]] + name = "github.com/stretchr/objx" + version = "~0.1.0" diff --git a/vendor/github.com/stretchr/testify/README.md b/vendor/github.com/stretchr/testify/README.md index e57b181..51b6df3 100644 --- a/vendor/github.com/stretchr/testify/README.md +++ b/vendor/github.com/stretchr/testify/README.md @@ -9,7 +9,6 @@ Features include: * [Easy assertions](#assert-package) * [Mocking](#mock-package) - * [HTTP response trapping](#http-package) * [Testing suite interfaces and functions](#suite-package) Get started: @@ -106,14 +105,6 @@ The `require` package provides same global functions as the `assert` package, bu See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details. - -[`http`](http://godoc.org/github.com/stretchr/testify/http "API documentation") package ---------------------------------------------------------------------------------------- - -The `http` package contains test objects useful for testing code that relies on the `net/http` package. Check out the [(deprecated) API documentation for the `http` package](http://godoc.org/github.com/stretchr/testify/http). - -We recommend you use [httptest](http://golang.org/pkg/net/http/httptest) instead. - [`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package ---------------------------------------------------------------------------------------- @@ -173,6 +164,29 @@ func TestSomething(t *testing.T) { // assert that the expectations were met testObj.AssertExpectations(t) + +} + +// TestSomethingElse is a second example of how to use our test object to +// make assertions about some target code we are testing. +// This time using a placeholder. Placeholders might be used when the +// data being passed in is normally dynamically generated and cannot be +// predicted beforehand (eg. containing hashes that are time sensitive) +func TestSomethingElse(t *testing.T) { + + // create an instance of our test object + testObj := new(MyMockedObject) + + // setup expectations with a placeholder in the argument list + testObj.On("DoSomething", mock.Anything).Return(true, nil) + + // call the code we are testing + targetFuncThatDoesSomethingWithObj(testObj) + + // assert that the expectations were met + testObj.AssertExpectations(t) + + } ``` @@ -268,8 +282,7 @@ Installation To install Testify, use `go get`: - * Latest version: go get github.com/stretchr/testify - * Specific version: go get gopkg.in/stretchr/testify.v1 + go get github.com/stretchr/testify This will then make the following packages available to you: @@ -303,10 +316,10 @@ To update Testify to the latest version, use `go get -u github.com/stretchr/test ------ -Version History -=============== +Supported go versions +================== - * 1.0 - New package versioning strategy adopted. +We support the three major Go versions, which are 1.8, 1.9 and 1.10 at the moment. ------ @@ -316,17 +329,3 @@ Contributing Please feel free to submit issues, fork the repository and send pull requests! When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it. - ------- - -Licence -======= -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell - -Please consider promoting this project if you find it useful. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 3e172f2..aa1c2b9 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -13,6 +13,9 @@ import ( // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Condition(t, comp, append([]interface{}{msg}, args...)...) } @@ -22,14 +25,18 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Contains(t, s, contains, append([]interface{}{msg}, args...)...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return DirExists(t, path, append([]interface{}{msg}, args...)...) } @@ -37,10 +44,11 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) -// -// Returns whether the assertion was successful (true) or not (false). +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } @@ -48,9 +56,10 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Empty(t, object, append([]interface{}{msg}, args...)...) } @@ -58,12 +67,13 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -72,9 +82,10 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) } @@ -82,9 +93,10 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args // and equal. // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -94,62 +106,80 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Error(t, err, append([]interface{}{msg}, args...)...) } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return False(t, value, append([]interface{}{msg}, args...)...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return FileExists(t, path, append([]interface{}{msg}, args...)...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } @@ -159,6 +189,9 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -168,6 +201,9 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -177,6 +213,9 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -184,51 +223,69 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -236,18 +293,20 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Len(t, object, length, append([]interface{}{msg}, args...)...) } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Nil(t, object, append([]interface{}{msg}, args...)...) } @@ -257,9 +316,10 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NoError(t, err, append([]interface{}{msg}, args...)...) } @@ -269,9 +329,10 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) } @@ -281,9 +342,10 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotEmpty(t, object, append([]interface{}{msg}, args...)...) } @@ -291,29 +353,32 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotNil(t, object, append([]interface{}{msg}, args...)...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotPanics(t, f, append([]interface{}{msg}, args...)...) } @@ -321,9 +386,10 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo // // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) } @@ -331,23 +397,28 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args .. // elements given in the specified subset(array, slice...). // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) } -// NotZerof asserts that i is not the zero value for its type and returns the truth. +// NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotZero(t, i, append([]interface{}{msg}, args...)...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Panics(t, f, append([]interface{}{msg}, args...)...) } @@ -355,9 +426,10 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } @@ -365,9 +437,10 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str // // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) } @@ -375,31 +448,37 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in // elements given in the specified subset(array, slice...). // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Subset(t, list, subset, append([]interface{}{msg}, args...)...) } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return True(t, value, append([]interface{}{msg}, args...)...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } -// Zerof asserts that i is the zero value for its type and returns the truth. +// Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Zero(t, i, append([]interface{}{msg}, args...)...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl index c5cc66f..d2bb0b8 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl @@ -1,4 +1,5 @@ {{.CommentFormat}} func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { + if h, ok := t.(tHelper); ok { h.Helper() } return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 7c4f497..de39f79 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -13,11 +13,17 @@ import ( // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Conditionf(a.t, comp, msg, args...) } @@ -27,9 +33,10 @@ func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{} // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Contains(a.t, s, contains, msgAndArgs...) } @@ -39,19 +46,26 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return DirExistsf(a.t, path, msg, args...) } @@ -59,10 +73,11 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bo // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])) -// -// Returns whether the assertion was successful (true) or not (false). +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return ElementsMatch(a.t, listA, listB, msgAndArgs...) } @@ -70,10 +85,11 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) -// -// Returns whether the assertion was successful (true) or not (false). +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return ElementsMatchf(a.t, listA, listB, msg, args...) } @@ -81,9 +97,10 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // a slice or a channel with len == 0. // // a.Empty(obj) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Empty(a.t, object, msgAndArgs...) } @@ -91,9 +108,10 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Emptyf(a.t, object, msg, args...) } @@ -101,12 +119,13 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // // a.Equal(123, 123) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Equal(a.t, expected, actual, msgAndArgs...) } @@ -115,9 +134,10 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualError(a.t, theError, errString, msgAndArgs...) } @@ -126,9 +146,10 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualErrorf(a.t, theError, errString, msg, args...) } @@ -136,9 +157,10 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a // and equal. // // a.EqualValues(uint32(123), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualValues(a.t, expected, actual, msgAndArgs...) } @@ -146,9 +168,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn // and equal. // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualValuesf(a.t, expected, actual, msg, args...) } @@ -156,12 +179,13 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // // a.Equalf(123, 123, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Equalf(a.t, expected, actual, msg, args...) } @@ -171,9 +195,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // if a.Error(err) { // assert.Equal(t, expectedError, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Error(a.t, err, msgAndArgs...) } @@ -183,115 +208,150 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Errorf(a.t, err, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } @@ -301,6 +361,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPError(a.t, handler, method, url, values, msgAndArgs...) } @@ -310,6 +373,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPErrorf(a.t, handler, method, url, values, msg, args...) } @@ -319,6 +385,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } @@ -328,6 +397,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } @@ -337,6 +409,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } @@ -346,6 +421,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } @@ -353,6 +431,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Implements(a.t, interfaceObject, object, msgAndArgs...) } @@ -360,96 +441,129 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return JSONEqf(a.t, expected, actual, msg, args...) } @@ -457,9 +571,10 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Len(a.t, object, length, msgAndArgs...) } @@ -467,27 +582,30 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Lenf(a.t, object, length, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Nilf(a.t, object, msg, args...) } @@ -497,9 +615,10 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) b // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NoError(a.t, err, msgAndArgs...) } @@ -509,9 +628,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NoErrorf(a.t, err, msg, args...) } @@ -521,9 +641,10 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotContains(a.t, s, contains, msgAndArgs...) } @@ -533,9 +654,10 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotContainsf(a.t, s, contains, msg, args...) } @@ -545,9 +667,10 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEmpty(a.t, object, msgAndArgs...) } @@ -557,9 +680,10 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEmptyf(a.t, object, msg, args...) } @@ -567,11 +691,12 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // // a.NotEqual(obj1, obj2) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEqual(a.t, expected, actual, msgAndArgs...) } @@ -579,47 +704,52 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEqualf(a.t, expected, actual, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotPanicsf(a.t, f, msg, args...) } @@ -627,9 +757,10 @@ func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{} // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotRegexp(a.t, rx, str, msgAndArgs...) } @@ -637,9 +768,10 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotRegexpf(a.t, rx, str, msg, args...) } @@ -647,9 +779,10 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // elements given in the specified subset(array, slice...). // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotSubset(a.t, list, subset, msgAndArgs...) } @@ -657,28 +790,36 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs // elements given in the specified subset(array, slice...). // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotSubsetf(a.t, list, subset, msg, args...) } -// NotZero asserts that i is not the zero value for its type and returns the truth. +// NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotZero(a.t, i, msgAndArgs...) } -// NotZerof asserts that i is not the zero value for its type and returns the truth. +// NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Panics(a.t, f, msgAndArgs...) } @@ -686,9 +827,10 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return PanicsWithValue(a.t, expected, f, msgAndArgs...) } @@ -696,18 +838,20 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgA // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Panicsf(a.t, f, msg, args...) } @@ -715,9 +859,10 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Regexp(a.t, rx, str, msgAndArgs...) } @@ -725,9 +870,10 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Regexpf(a.t, rx, str, msg, args...) } @@ -735,9 +881,10 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // elements given in the specified subset(array, slice...). // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Subset(a.t, list, subset, msgAndArgs...) } @@ -745,54 +892,65 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... // elements given in the specified subset(array, slice...). // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return WithinDurationf(a.t, expected, actual, delta, msg, args...) } -// Zero asserts that i is the zero value for its type and returns the truth. +// Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Zero(a.t, i, msgAndArgs...) } -// Zerof asserts that i is the zero value for its type and returns the truth. +// Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Zerof(a.t, i, msg, args...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl index 99f9acf..188bb9e 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl @@ -1,4 +1,5 @@ {{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { + if h, ok := a.t.(tHelper); ok { h.Helper() } return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 9d387bc..5bdec56 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -27,6 +27,22 @@ type TestingT interface { Errorf(format string, args ...interface{}) } +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool + +// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool + // Comparison a custom function that returns true on success and false on failure type Comparison func() (success bool) @@ -38,21 +54,23 @@ type Comparison func() (success bool) // // This function does no assertion of any kind. func ObjectsAreEqual(expected, actual interface{}) bool { - if expected == nil || actual == nil { return expected == actual } - if exp, ok := expected.([]byte); ok { - act, ok := actual.([]byte) - if !ok { - return false - } else if exp == nil || act == nil { - return exp == nil && act == nil - } - return bytes.Equal(exp, act) - } - return reflect.DeepEqual(expected, actual) + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) } // ObjectsAreEqualValues gets whether two objects are equal, or if their @@ -156,21 +174,6 @@ func isTest(name, prefix string) bool { return !unicode.IsLower(rune) } -// getWhitespaceString returns a string that is long enough to overwrite the default -// output from the go testing framework. -func getWhitespaceString() string { - - _, file, line, ok := runtime.Caller(1) - if !ok { - return "" - } - parts := strings.Split(file, "/") - file = parts[len(parts)-1] - - return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) - -} - func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { if len(msgAndArgs) == 0 || msgAndArgs == nil { return "" @@ -195,7 +198,7 @@ func indentMessageLines(message string, longestLabelLen int) string { // no need to align first line because it starts at the correct location (after the label) if i != 0 { // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } outBuf.WriteString(scanner.Text()) } @@ -209,6 +212,9 @@ type failNower interface { // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } Fail(t, failureMessage, msgAndArgs...) // We cannot extend TestingT with FailNow() and @@ -227,8 +233,11 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } content := []labeledContent{ - {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")}, + {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, {"Error", failureMessage}, } @@ -244,7 +253,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { content = append(content, labeledContent{"Messages", message}) } - t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...)) + t.Errorf("\n%s", ""+labeledOutput(content...)) return false } @@ -256,7 +265,7 @@ type labeledContent struct { // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: // -// \r\t{{label}}:{{align_spaces}}\t{{content}}\n +// \t{{label}}:{{align_spaces}}\t{{content}}\n // // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this @@ -272,7 +281,7 @@ func labeledOutput(content ...labeledContent) string { } var output string for _, v := range content { - output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" } return output } @@ -281,6 +290,9 @@ func labeledOutput(content ...labeledContent) string { // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } interfaceType := reflect.TypeOf(interfaceObject).Elem() if object == nil { @@ -295,6 +307,9 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) @@ -307,12 +322,13 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs // // assert.Equal(t, 123, 123) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", expected, actual, err), msgAndArgs...) @@ -350,9 +366,10 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) { // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !ObjectsAreEqualValues(expected, actual) { diff := diff(expected, actual) @@ -369,15 +386,16 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } return Equal(t, expected, actual, msgAndArgs...) @@ -387,9 +405,10 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) -// -// Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !isNil(object) { return true } @@ -414,9 +433,10 @@ func isNil(object interface{}) bool { // Nil asserts that the specified object is nil. // // assert.Nil(t, err) -// -// Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if isNil(object) { return true } @@ -455,9 +475,10 @@ func isEmpty(object interface{}) bool { // a slice or a channel with len == 0. // // assert.Empty(t, obj) -// -// Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } pass := isEmpty(object) if !pass { @@ -474,9 +495,10 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } pass := !isEmpty(object) if !pass { @@ -503,9 +525,10 @@ func getLen(x interface{}) (ok bool, length int) { // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) -// -// Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, l := getLen(object) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) @@ -520,9 +543,15 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) // True asserts that the specified value is true. // // assert.True(t, myBool) -// -// Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if h, ok := t.(interface { + Helper() + }); ok { + h.Helper() + } if value != true { return Fail(t, "Should be true", msgAndArgs...) @@ -535,9 +564,10 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { // False asserts that the specified value is false. // // assert.False(t, myBool) -// -// Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if value != false { return Fail(t, "Should be false", msgAndArgs...) @@ -551,11 +581,12 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { // // assert.NotEqual(t, obj1, obj2) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", expected, actual, err), msgAndArgs...) @@ -613,9 +644,10 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) { // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") -// -// Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, found := includeElement(s, contains) if !ok { @@ -635,9 +667,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") -// -// Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, found := includeElement(s, contains) if !ok { @@ -655,9 +688,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) // elements given in the specified subset(array, slice...). // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if subset == nil { return true // we consider nil to be equal to the nil set } @@ -698,9 +732,10 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok // elements given in the specified subset(array, slice...). // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if subset == nil { return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) } @@ -741,10 +776,11 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])) -// -// Returns whether the assertion was successful (true) or not (false). +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if isEmpty(listA) && isEmpty(listB) { return true } @@ -795,6 +831,9 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } result := comp() if !result { Fail(t, "Condition failed!", msgAndArgs...) @@ -831,12 +870,13 @@ func didPanic(f PanicTestFunc) (bool, interface{}) { // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } return true @@ -846,16 +886,17 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } funcDidPanic, panicValue := didPanic(f) if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } if panicValue != expected { - return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...) } return true @@ -864,12 +905,13 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) -// -// Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if funcDidPanic, panicValue := didPanic(f); funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true @@ -878,9 +920,10 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -// -// Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } dt := expected.Sub(actual) if dt < -delta || dt > delta { @@ -929,9 +972,10 @@ func toFloat(x interface{}) (float64, bool) { // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } af, aok := toFloat(expected) bf, bok := toFloat(actual) @@ -958,6 +1002,9 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { @@ -979,6 +1026,9 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Map || reflect.TypeOf(expected).Kind() != reflect.Map { @@ -989,7 +1039,7 @@ func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, m actualMap := reflect.ValueOf(actual) if expectedMap.Len() != actualMap.Len() { - return Fail(t, "Arguments must have the same numbe of keys", msgAndArgs...) + return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) } for _, k := range expectedMap.MapKeys() { @@ -1035,9 +1085,10 @@ func calcRelativeError(expected, actual interface{}) (float64, error) { } // InEpsilon asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { return Fail(t, err.Error(), msgAndArgs...) @@ -1052,6 +1103,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { @@ -1081,9 +1135,10 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err != nil { return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) } @@ -1097,9 +1152,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err == nil { return Fail(t, "An error is expected but got nil.", msgAndArgs...) @@ -1113,9 +1169,10 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) -// -// Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !Error(t, theError, msgAndArgs...) { return false } @@ -1148,9 +1205,10 @@ func matchRegexp(rx interface{}, str interface{}) bool { // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } match := matchRegexp(rx, str) @@ -1165,9 +1223,10 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } match := matchRegexp(rx, str) if match { @@ -1178,16 +1237,22 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf } -// Zero asserts that i is the zero value for its type and returns the truth. +// Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) } return true } -// NotZero asserts that i is not the zero value for its type and returns the truth. +// NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) } @@ -1196,6 +1261,9 @@ func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { @@ -1211,6 +1279,9 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { @@ -1227,9 +1298,10 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -// -// Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } var expectedJSONAsInterface, actualJSONAsInterface interface{} if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { @@ -1268,12 +1340,18 @@ func diff(expected interface{}, actual interface{}) string { return "" } - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { return "" } - e := spewConfig.Sdump(expected) - a := spewConfig.Sdump(actual) + var e, a string + if ek != reflect.String { + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } else { + e = expected.(string) + a = actual.(string) + } diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), @@ -1310,3 +1388,7 @@ var spewConfig = spew.ConfigState{ DisableCapacities: true, SortKeys: true, } + +type tHelper interface { + Helper() +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions_test.go b/vendor/github.com/stretchr/testify/assert/assertions_test.go index 6757bd1..91b5ee9 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions_test.go +++ b/vendor/github.com/stretchr/testify/assert/assertions_test.go @@ -2,6 +2,7 @@ package assert import ( "bytes" + "encoding/json" "errors" "fmt" "io" @@ -250,6 +251,21 @@ func (t *bufferT) Errorf(format string, args ...interface{}) { t.buf.WriteString(decorate(fmt.Sprintf(format, args...))) } +func TestStringEqual(t *testing.T) { + for i, currCase := range []struct { + equalWant string + equalGot string + msgAndArgs []interface{} + want string + }{ + {equalWant: "hi, \nmy name is", equalGot: "what,\nmy name is", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"hi, \\\\nmy name is\"\n\\s+actual\\s+: \"what,\\\\nmy name is\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1,2 \\+1,2 @@\n\\s+-hi, \n\\s+\\+what,\n\\s+my name is"}, + } { + mockT := &bufferT{} + Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) + Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i) + } +} + func TestEqualFormatting(t *testing.T) { for i, currCase := range []struct { equalWant string @@ -257,8 +273,8 @@ func TestEqualFormatting(t *testing.T) { msgAndArgs []interface{} want string }{ - {equalWant: "want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \tactual : \"got\"\n"}, - {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \tactual : \"got\"\n\t\t\r\tMessages: \thello, world!\n"}, + {equalWant: "want", equalGot: "got", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n"}, + {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+hello, world!\n"}, } { mockT := &bufferT{} Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) @@ -1579,3 +1595,199 @@ func TestEqualArgsValidation(t *testing.T) { err := validateEqualArgs(time.Now, time.Now) EqualError(t, err, "cannot take func type as argument") } + +func ExampleComparisonAssertionFunc() { + t := &testing.T{} // provided by test + + adder := func(x, y int) int { + return x + y + } + + type args struct { + x int + y int + } + + tests := []struct { + name string + args args + expect int + assertion ComparisonAssertionFunc + }{ + {"2+2=4", args{2, 2}, 4, Equal}, + {"2+2!=5", args{2, 2}, 5, NotEqual}, + {"2+3==5", args{2, 3}, 5, Exactly}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) + }) + } +} + +func TestComparisonAssertionFunc(t *testing.T) { + type iface interface { + Name() string + } + + tests := []struct { + name string + expect interface{} + got interface{} + assertion ComparisonAssertionFunc + }{ + {"implements", (*iface)(nil), t, Implements}, + {"isType", (*testing.T)(nil), t, IsType}, + {"equal", t, t, Equal}, + {"equalValues", t, t, EqualValues}, + {"exactly", t, t, Exactly}, + {"notEqual", t, nil, NotEqual}, + {"notContains", []int{1, 2, 3}, 4, NotContains}, + {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, + {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, + {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, + {"regexp", "^t.*y$", "testify", Regexp}, + {"notRegexp", "^t.*y$", "Testify", NotRegexp}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.expect, tt.got) + }) + } +} + +func ExampleValueAssertionFunc() { + t := &testing.T{} // provided by test + + dumbParse := func(input string) interface{} { + var x interface{} + json.Unmarshal([]byte(input), &x) + return x + } + + tests := []struct { + name string + arg string + assertion ValueAssertionFunc + }{ + {"true is not nil", "true", NotNil}, + {"empty string is nil", "", Nil}, + {"zero is not nil", "0", NotNil}, + {"zero is zero", "0", Zero}, + {"false is zero", "false", Zero}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, dumbParse(tt.arg)) + }) + } +} + +func TestValueAssertionFunc(t *testing.T) { + tests := []struct { + name string + value interface{} + assertion ValueAssertionFunc + }{ + {"notNil", true, NotNil}, + {"nil", nil, Nil}, + {"empty", []int{}, Empty}, + {"notEmpty", []int{1}, NotEmpty}, + {"zero", false, Zero}, + {"notZero", 42, NotZero}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.value) + }) + } +} + +func ExampleBoolAssertionFunc() { + t := &testing.T{} // provided by test + + isOkay := func(x int) bool { + return x >= 42 + } + + tests := []struct { + name string + arg int + assertion BoolAssertionFunc + }{ + {"-1 is bad", -1, False}, + {"42 is good", 42, True}, + {"41 is bad", 41, False}, + {"45 is cool", 45, True}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, isOkay(tt.arg)) + }) + } +} + +func TestBoolAssertionFunc(t *testing.T) { + tests := []struct { + name string + value bool + assertion BoolAssertionFunc + }{ + {"true", true, True}, + {"false", false, False}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.value) + }) + } +} + +func ExampleErrorAssertionFunc() { + t := &testing.T{} // provided by test + + dumbParseNum := func(input string, v interface{}) error { + return json.Unmarshal([]byte(input), v) + } + + tests := []struct { + name string + arg string + assertion ErrorAssertionFunc + }{ + {"1.2 is number", "1.2", NoError}, + {"1.2.3 not number", "1.2.3", Error}, + {"true is not number", "true", Error}, + {"3 is number", "3", NoError}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var x float64 + tt.assertion(t, dumbParseNum(tt.arg, &x)) + }) + } +} + +func TestErrorAssertionFunc(t *testing.T) { + tests := []struct { + name string + err error + assertion ErrorAssertionFunc + }{ + {"noError", nil, NoError}, + {"error", errors.New("whoops"), Error}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.err) + }) + } +} diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index 3101e78..df46fa7 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,10 +12,11 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + req, err := http.NewRequest(method, url, nil) if err != nil { return -1, err } + req.URL.RawQuery = values.Encode() handler(w, req) return w.Code, nil } @@ -26,6 +27,9 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) ( // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -46,6 +50,9 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -66,6 +73,9 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -95,10 +105,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) @@ -112,10 +125,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions_test.go b/vendor/github.com/stretchr/testify/assert/http_assertions_test.go index 3ab7683..112beaf 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions_test.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions_test.go @@ -89,6 +89,35 @@ func httpHelloName(w http.ResponseWriter, r *http.Request) { w.Write([]byte(fmt.Sprintf("Hello, %s!", name))) } +func TestHTTPRequestWithNoParams(t *testing.T) { + var got *http.Request + handler := func(w http.ResponseWriter, r *http.Request) { + got = r + w.WriteHeader(http.StatusOK) + } + + True(t, HTTPSuccess(t, handler, "GET", "/url", nil)) + + Empty(t, got.URL.Query()) + Equal(t, "/url", got.URL.RequestURI()) +} + +func TestHTTPRequestWithParams(t *testing.T) { + var got *http.Request + handler := func(w http.ResponseWriter, r *http.Request) { + got = r + w.WriteHeader(http.StatusOK) + } + params := url.Values{} + params.Add("id", "12345") + + True(t, HTTPSuccess(t, handler, "GET", "/url", params)) + + Equal(t, url.Values{"id": []string{"12345"}}, got.URL.Query()) + Equal(t, "/url?id=12345", got.URL.String()) + Equal(t, "/url?id=12345", got.URL.RequestURI()) +} + func TestHttpBody(t *testing.T) { assert := New(t) mockT := new(testing.T) diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go index 208b838..cc4f642 100644 --- a/vendor/github.com/stretchr/testify/mock/mock.go +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -42,6 +42,9 @@ type Call struct { // this method is called. ReturnArguments Arguments + // Holds the caller info for the On() call + callerInfo []string + // The number of times to return the return arguments when setting // expectations. 0 means to always return the value. Repeatability int @@ -64,12 +67,13 @@ type Call struct { RunFn func(Arguments) } -func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call { +func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call { return &Call{ Parent: parent, Method: methodName, Arguments: methodArguments, ReturnArguments: make([]interface{}, 0), + callerInfo: callerInfo, Repeatability: 0, WaitFor: nil, RunFn: nil, @@ -187,6 +191,10 @@ type Mock struct { // Holds the calls that were made to this mocked object. Calls []Call + // test is An optional variable that holds the test struct, to be used when an + // invalid mock call was made. + test TestingT + // TestData holds any data that might be useful for testing. Testify ignores // this data completely allowing you to do whatever you like with it. testData objx.Map @@ -209,6 +217,27 @@ func (m *Mock) TestData() objx.Map { Setting expectations */ +// Test sets the test struct variable of the mock object +func (m *Mock) Test(t TestingT) { + m.mutex.Lock() + defer m.mutex.Unlock() + m.test = t +} + +// fail fails the current test with the given formatted format and args. +// In case that a test was defined, it uses the test APIs for failing a test, +// otherwise it uses panic. +func (m *Mock) fail(format string, args ...interface{}) { + m.mutex.Lock() + defer m.mutex.Unlock() + + if m.test == nil { + panic(fmt.Sprintf(format, args...)) + } + m.test.Errorf(format, args...) + m.test.FailNow() +} + // On starts a description of an expectation of the specified method // being called. // @@ -222,7 +251,7 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call { m.mutex.Lock() defer m.mutex.Unlock() - c := newCall(m, methodName, arguments...) + c := newCall(m, methodName, assert.CallerInfo(), arguments...) m.ExpectedCalls = append(m.ExpectedCalls, c) return c } @@ -245,27 +274,25 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, * return -1, nil } -func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) { - diffCount := 0 +func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) { + var diffCount int var closestCall *Call + var err string for _, call := range m.expectedCalls() { if call.Method == method { - _, tempDiffCount := call.Arguments.Diff(arguments) + errInfo, tempDiffCount := call.Arguments.Diff(arguments) if tempDiffCount < diffCount || diffCount == 0 { diffCount = tempDiffCount closestCall = call + err = errInfo } } } - if closestCall == nil { - return false, nil - } - - return true, closestCall + return closestCall, err } func callString(method string, arguments Arguments, includeArgumentValues bool) string { @@ -312,6 +339,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments { // If Call.WaitFor is set, blocks until the channel is closed or receives a message. func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments { m.mutex.Lock() + //TODO: could combine expected and closes in single loop found, call := m.findExpectedCall(methodName, arguments...) if found < 0 { @@ -322,13 +350,18 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen // b) the arguments are not what was expected, or // c) the developer has forgotten to add an accompanying On...Return pair. - closestFound, closestCall := m.findClosestCall(methodName, arguments...) + closestCall, mismatch := m.findClosestCall(methodName, arguments...) m.mutex.Unlock() - if closestFound { - panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(methodName, arguments, true), callString(methodName, closestCall.Arguments, true), diffArguments(closestCall.Arguments, arguments))) + if closestCall != nil { + m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s", + callString(methodName, arguments, true), + callString(methodName, closestCall.Arguments, true), + diffArguments(closestCall.Arguments, arguments), + strings.TrimSpace(mismatch), + ) } else { - panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())) + m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()) } } @@ -340,7 +373,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen call.totalCalls++ // add the call - m.Calls = append(m.Calls, *newCall(m, methodName, arguments...)) + m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...)) m.mutex.Unlock() // block if specified @@ -378,6 +411,9 @@ type assertExpectationser interface { // // Calls may have occurred in any order. func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } for _, obj := range testObjects { if m, ok := obj.(Mock); ok { t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") @@ -385,6 +421,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { } m := obj.(assertExpectationser) if !m.AssertExpectations(t) { + t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) return false } } @@ -394,6 +431,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { // AssertExpectations asserts that everything specified with On and Return was // in fact called as expected. Calls may have occurred in any order. func (m *Mock) AssertExpectations(t TestingT) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } m.mutex.Lock() defer m.mutex.Unlock() var somethingMissing bool @@ -405,13 +445,14 @@ func (m *Mock) AssertExpectations(t TestingT) bool { if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 { somethingMissing = true failedExpectations++ - t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) + t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo) } else { if expectedCall.Repeatability > 0 { somethingMissing = true failedExpectations++ + t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo) } else { - t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) + t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) } } } @@ -425,6 +466,9 @@ func (m *Mock) AssertExpectations(t TestingT) bool { // AssertNumberOfCalls asserts that the method was called expectedCalls times. func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } m.mutex.Lock() defer m.mutex.Unlock() var actualCalls int @@ -439,11 +483,22 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls // AssertCalled asserts that the method was called. // It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } m.mutex.Lock() defer m.mutex.Unlock() - if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) { - t.Logf("%v", m.expectedCalls()) - return false + if !m.methodWasCalled(methodName, arguments) { + var calledWithArgs []string + for _, call := range m.calls() { + calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments)) + } + if len(calledWithArgs) == 0 { + return assert.Fail(t, "Should have called with given arguments", + fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments)) + } + return assert.Fail(t, "Should have called with given arguments", + fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n"))) } return true } @@ -451,11 +506,14 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac // AssertNotCalled asserts that the method was not called. // It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } m.mutex.Lock() defer m.mutex.Unlock() - if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) { - t.Logf("%v", m.expectedCalls()) - return false + if m.methodWasCalled(methodName, arguments) { + return assert.Fail(t, "Should not have called with given arguments", + fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments)) } return true } @@ -495,7 +553,7 @@ type Arguments []interface{} const ( // Anything is used in Diff and Assert when the argument being tested // shouldn't be taken into consideration. - Anything string = "mock.Anything" + Anything = "mock.Anything" ) // AnythingOfTypeArgument is a string that contains the type of an argument @@ -598,6 +656,7 @@ func (args Arguments) Is(objects ...interface{}) bool { // // Returns the diff string and number of differences found. func (args Arguments) Diff(objects []interface{}) (string, int) { + //TODO: could return string as error and nil for No difference var output = "\n" var differences int @@ -609,25 +668,30 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { for i := 0; i < maxArgCount; i++ { var actual, expected interface{} + var actualFmt, expectedFmt string if len(objects) <= i { actual = "(Missing)" + actualFmt = "(Missing)" } else { actual = objects[i] + actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual) } if len(args) <= i { expected = "(Missing)" + expectedFmt = "(Missing)" } else { expected = args[i] + expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected) } if matcher, ok := expected.(argumentMatcher); ok { if matcher.Matches(actual) { - output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher) + output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher) } else { differences++ - output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher) + output = fmt.Sprintf("%s\t%d: PASS: %s not matched by %s\n", output, i, actualFmt, matcher) } } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { @@ -635,7 +699,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { // not match differences++ - output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual) + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) } } else { @@ -644,11 +708,11 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { // match - output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected) + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) } else { // not match differences++ - output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected) + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) } } @@ -665,6 +729,9 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { // Assert compares the arguments with the specified objects and fails if // they do not exactly match. func (args Arguments) Assert(t TestingT, objects ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } // get the differences diff, diffCount := args.Diff(objects) @@ -812,3 +879,7 @@ var spewConfig = spew.ConfigState{ DisableCapacities: true, SortKeys: true, } + +type tHelper interface { + Helper() +} diff --git a/vendor/github.com/stretchr/testify/mock/mock_test.go b/vendor/github.com/stretchr/testify/mock/mock_test.go index cb245ba..978eae2 100644 --- a/vendor/github.com/stretchr/testify/mock/mock_test.go +++ b/vendor/github.com/stretchr/testify/mock/mock_test.go @@ -3,6 +3,8 @@ package mock import ( "errors" "fmt" + "regexp" + "runtime" "sync" "testing" "time" @@ -90,6 +92,34 @@ func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) return args.Error(0) } +// MockTestingT mocks a test struct +type MockTestingT struct { + logfCount, errorfCount, failNowCount int +} + +const mockTestingTFailNowCalled = "FailNow was called" + +func (m *MockTestingT) Logf(string, ...interface{}) { + m.logfCount++ +} + +func (m *MockTestingT) Errorf(string, ...interface{}) { + m.errorfCount++ +} + +// FailNow mocks the FailNow call. +// It panics in order to mimic the FailNow behavior in the sense that +// the execution stops. +// When expecting this method, the call that invokes it should use the following code: +// +// assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {...}) +func (m *MockTestingT) FailNow() { + m.failNowCount++ + + // this function should panic now to stop the execution as expected + panic(mockTestingTFailNowCalled) +} + /* Mock */ @@ -119,6 +149,8 @@ func Test_Mock_Chained_On(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) + // determine our current line number so we can assert the expected calls callerInfo properly + _, _, line, _ := runtime.Caller(0) mockedService. On("TheExampleMethod", 1, 2, 3). Return(0). @@ -126,17 +158,19 @@ func Test_Mock_Chained_On(t *testing.T) { Return(nil) expectedCalls := []*Call{ - &Call{ + { Parent: &mockedService.Mock, Method: "TheExampleMethod", Arguments: []interface{}{1, 2, 3}, ReturnArguments: []interface{}{0}, + callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+2)}, }, - &Call{ + { Parent: &mockedService.Mock, Method: "TheExampleMethod3", Arguments: []interface{}{AnythingOfType("*mock.ExampleType")}, ReturnArguments: []interface{}{nil}, + callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+4)}, }, } assert.Equal(t, expectedCalls, mockedService.ExpectedCalls) @@ -198,6 +232,34 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) { }) } +func TestMock_WithTest(t *testing.T) { + var ( + mockedService TestExampleImplementation + mockedTest MockTestingT + ) + + mockedService.Test(&mockedTest) + mockedService.On("TheExampleMethod", 1, 2, 3).Return(0, nil) + + // Test that on an expected call, the test was not failed + + mockedService.TheExampleMethod(1, 2, 3) + + // Assert that Errorf and FailNow were not called + assert.Equal(t, 0, mockedTest.errorfCount) + assert.Equal(t, 0, mockedTest.failNowCount) + + // Test that on unexpected call, the mocked test was called to fail the test + + assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() { + mockedService.TheExampleMethod(1, 1, 1) + }) + + // Assert that Errorf and FailNow were called once + assert.Equal(t, 1, mockedTest.errorfCount) + assert.Equal(t, 1, mockedTest.failNowCount) +} + func Test_Mock_On_WithPtrArgMatcher(t *testing.T) { var mockedService TestExampleImplementation @@ -1125,8 +1187,8 @@ func Test_Arguments_Diff(t *testing.T) { diff, count = args.Diff([]interface{}{"Hello World", 456, "false"}) assert.Equal(t, 2, count) - assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`) - assert.Contains(t, diff, `false != %!s(bool=true)`) + assert.Contains(t, diff, `(int=456) != (int=123)`) + assert.Contains(t, diff, `(string=false) != (bool=true)`) } @@ -1138,7 +1200,7 @@ func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) { diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"}) assert.Equal(t, 3, count) - assert.Contains(t, diff, `extra != (Missing)`) + assert.Contains(t, diff, `(string=extra) != (Missing)`) } @@ -1180,7 +1242,7 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) { diff, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 1, count) - assert.Contains(t, diff, `string != type int - %!s(int=123)`) + assert.Contains(t, diff, `string != type int - (int=123)`) } @@ -1192,14 +1254,14 @@ func Test_Arguments_Diff_WithArgMatcher(t *testing.T) { diff, count := args.Diff([]interface{}{"string", 124, true}) assert.Equal(t, 1, count) - assert.Contains(t, diff, `%!s(int=124) not matched by func(int) bool`) + assert.Contains(t, diff, `(int=124) not matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", false, true}) assert.Equal(t, 1, count) - assert.Contains(t, diff, `%!s(bool=false) not matched by func(int) bool`) + assert.Contains(t, diff, `(bool=false) not matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", 123, false}) - assert.Contains(t, diff, `%!s(int=123) matched by func(int) bool`) + assert.Contains(t, diff, `(int=123) matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 0, count) @@ -1260,7 +1322,7 @@ func Test_Arguments_Bool(t *testing.T) { func Test_WaitUntil_Parallel(t *testing.T) { // make a test impl object - var mockedService *TestExampleImplementation = new(TestExampleImplementation) + var mockedService = new(TestExampleImplementation) ch1 := make(chan time.Time) ch2 := make(chan time.Time) @@ -1323,6 +1385,37 @@ func (s *timer) GetTime(i int) string { return s.Called(i).Get(0).(string) } +type tCustomLogger struct { + *testing.T + logs []string + errs []string +} + +func (tc *tCustomLogger) Logf(format string, args ...interface{}) { + tc.T.Logf(format, args...) + tc.logs = append(tc.logs, fmt.Sprintf(format, args...)) +} + +func (tc *tCustomLogger) Errorf(format string, args ...interface{}) { + tc.errs = append(tc.errs, fmt.Sprintf(format, args...)) +} + +func (tc *tCustomLogger) FailNow() {} + +func TestLoggingAssertExpectations(t *testing.T) { + m := new(timer) + m.On("GetTime", 0).Return("") + tcl := &tCustomLogger{t, []string{}, []string{}} + + AssertExpectationsForObjects(tcl, m, new(TestExampleImplementation)) + + require.Equal(t, 1, len(tcl.errs)) + assert.Regexp(t, regexp.MustCompile("(?s)FAIL: 0 out of 1 expectation\\(s\\) were met.*The code you are testing needs to make 1 more call\\(s\\).*"), tcl.errs[0]) + require.Equal(t, 2, len(tcl.logs)) + assert.Regexp(t, regexp.MustCompile("(?s)FAIL:\tGetTime\\(int\\).*"), tcl.logs[0]) + require.Equal(t, "Expectations didn't match for Mock: *mock.timer", tcl.logs[1]) +} + func TestAfterTotalWaitTimeWhileExecution(t *testing.T) { waitDuration := 1 total, waitMs := 5, time.Millisecond*time.Duration(waitDuration) @@ -1342,11 +1435,63 @@ func TestAfterTotalWaitTimeWhileExecution(t *testing.T) { elapsedTime := end.Sub(start) assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs)) assert.Equal(t, total, len(results)) - for i, _ := range results { + for i := range results { assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same") } } +func TestArgumentMatcherToPrintMismatch(t *testing.T) { + defer func() { + if r := recover(); r != nil { + matchingExp := regexp.MustCompile( + `\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool`) + assert.Regexp(t, matchingExp, r) + } + }() + + m := new(timer) + m.On("GetTime", MatchedBy(func(i int) bool { return false })).Return("SomeTime").Once() + + res := m.GetTime(1) + require.Equal(t, "SomeTime", res) + m.AssertExpectations(t) +} + +func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) { + defer func() { + if r := recover(); r != nil { + matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod(int,int,int)`, `0: 1\s+1: 1\s+2: 2`, `0: 1\s+1: 1\s+2: 1`, `0: PASS: \(int=1\) == \(int=1\)\s+1: PASS: \(int=1\) == \(int=1\)\s+2: FAIL: \(int=2\) != \(int=1\)`)) + assert.Regexp(t, matchingExp, r) + } + }() + + m := new(TestExampleImplementation) + m.On("TheExampleMethod", 1, 1, 1).Return(1, nil).Once() + m.On("TheExampleMethod", 2, 2, 2).Return(2, nil).Once() + + m.TheExampleMethod(1, 1, 2) +} + +func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) { + defer func() { + if r := recover(); r != nil { + matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "0: 1", "0: 999", `0: FAIL: \(int=1\) != \(int=999\)`)) + assert.Regexp(t, matchingExp, r) + } + }() + + m := new(timer) + m.On("GetTime", 999).Return("SomeTime").Once() + + _ = m.GetTime(1) +} + +func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string { + rMethod := regexp.QuoteMeta(method) + return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+%s\s+The closest call I have is:\s+%s\s+%s\s+Diff: %s`, + rMethod, calledArg, rMethod, expectedArg, diff) +} + func ConcurrencyTestMethod(m *Mock) { m.Called() } diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index a21d02f..535f293 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -14,16 +14,24 @@ import ( // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { - if !assert.Condition(t, comp, msgAndArgs...) { - t.FailNow() + if assert.Condition(t, comp, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { - if !assert.Conditionf(t, comp, msg, args...) { - t.FailNow() + if assert.Conditionf(t, comp, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Contains asserts that the specified string, list(array, slice...) or map contains the @@ -32,12 +40,14 @@ func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interfac // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") -// -// Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if !assert.Contains(t, s, contains, msgAndArgs...) { - t.FailNow() + if assert.Contains(t, s, contains, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Containsf asserts that the specified string, list(array, slice...) or map contains the @@ -46,91 +56,111 @@ func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...int // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if !assert.Containsf(t, s, contains, msg, args...) { - t.FailNow() + if assert.Containsf(t, s, contains, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if !assert.DirExists(t, path, msgAndArgs...) { - t.FailNow() + if assert.DirExists(t, path, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if !assert.DirExistsf(t, path, msg, args...) { - t.FailNow() + if assert.DirExistsf(t, path, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])) -// -// Returns whether the assertion was successful (true) or not (false). +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if !assert.ElementsMatch(t, listA, listB, msgAndArgs...) { - t.FailNow() + if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) -// -// Returns whether the assertion was successful (true) or not (false). +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if !assert.ElementsMatchf(t, listA, listB, msg, args...) { - t.FailNow() + if assert.ElementsMatchf(t, listA, listB, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) -// -// Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.Empty(t, object, msgAndArgs...) { - t.FailNow() + if assert.Empty(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.Emptyf(t, object, msg, args...) { - t.FailNow() + if assert.Emptyf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.Equal(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.Equal(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualError asserts that a function returned an error (i.e. not `nil`) @@ -138,12 +168,14 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...i // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) -// -// Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { - if !assert.EqualError(t, theError, errString, msgAndArgs...) { - t.FailNow() + if assert.EqualError(t, theError, errString, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) @@ -151,51 +183,59 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { - if !assert.EqualErrorf(t, theError, errString, msg, args...) { - t.FailNow() + if assert.EqualErrorf(t, theError, errString, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.EqualValues(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.EqualValues(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualValuesf asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.EqualValuesf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.EqualValuesf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Equalf asserts that two objects are equal. // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.Equalf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.Equalf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Error asserts that a function returned an error (i.e. not `nil`). @@ -204,12 +244,14 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) { - if !assert.Error(t, err, msgAndArgs...) { - t.FailNow() + if assert.Error(t, err, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Errorf asserts that a function returned an error (i.e. not `nil`). @@ -218,146 +260,196 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) { // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func Errorf(t TestingT, err error, msg string, args ...interface{}) { - if !assert.Errorf(t, err, msg, args...) { - t.FailNow() + if assert.Errorf(t, err, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.Exactly(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.Exactly(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.Exactlyf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.Exactlyf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if !assert.Fail(t, failureMessage, msgAndArgs...) { - t.FailNow() + if assert.Fail(t, failureMessage, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if !assert.FailNow(t, failureMessage, msgAndArgs...) { - t.FailNow() + if assert.FailNow(t, failureMessage, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if !assert.FailNowf(t, failureMessage, msg, args...) { - t.FailNow() + if assert.FailNowf(t, failureMessage, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if !assert.Failf(t, failureMessage, msg, args...) { - t.FailNow() + if assert.Failf(t, failureMessage, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // False asserts that the specified value is false. // // assert.False(t, myBool) -// -// Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) { - if !assert.False(t, value, msgAndArgs...) { - t.FailNow() + if assert.False(t, value, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Falsef(t TestingT, value bool, msg string, args ...interface{}) { - if !assert.Falsef(t, value, msg, args...) { - t.FailNow() + if assert.Falsef(t, value, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if !assert.FileExists(t, path, msgAndArgs...) { - t.FailNow() + if assert.FileExists(t, path, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if !assert.FileExistsf(t, path, msg, args...) { - t.FailNow() + if assert.FileExistsf(t, path, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if !assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { - t.FailNow() + if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if !assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { - t.FailNow() + if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if !assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { - t.FailNow() + if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if !assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { - t.FailNow() + if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPError asserts that a specified handler returns an error status code. @@ -366,9 +458,13 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPErrorf asserts that a specified handler returns an error status code. @@ -377,9 +473,13 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPRedirect asserts that a specified handler returns a redirect status code. @@ -388,9 +488,13 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPRedirectf asserts that a specified handler returns a redirect status code. @@ -399,9 +503,13 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPSuccess asserts that a specified handler returns a success status code. @@ -410,9 +518,13 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPSuccessf asserts that a specified handler returns a success status code. @@ -421,191 +533,255 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if !assert.Implements(t, interfaceObject, object, msgAndArgs...) { - t.FailNow() + if assert.Implements(t, interfaceObject, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if !assert.Implementsf(t, interfaceObject, object, msg, args...) { - t.FailNow() + if assert.Implementsf(t, interfaceObject, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilon asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { - t.FailNow() + if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if !assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { - t.FailNow() + if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if !assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { - t.FailNow() + if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonf asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if !assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { - t.FailNow() + if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if !assert.IsType(t, expectedType, object, msgAndArgs...) { - t.FailNow() + if assert.IsType(t, expectedType, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if !assert.IsTypef(t, expectedType, object, msg, args...) { - t.FailNow() + if assert.IsTypef(t, expectedType, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -// -// Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if !assert.JSONEq(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.JSONEq(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if !assert.JSONEqf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.JSONEqf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) -// -// Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { - if !assert.Len(t, object, length, msgAndArgs...) { - t.FailNow() + if assert.Len(t, object, length, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { - if !assert.Lenf(t, object, length, msg, args...) { - t.FailNow() + if assert.Lenf(t, object, length, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) -// -// Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.Nil(t, object, msgAndArgs...) { - t.FailNow() + if assert.Nil(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.Nilf(t, object, msg, args...) { - t.FailNow() + if assert.Nilf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NoError asserts that a function returned no error (i.e. `nil`). @@ -614,12 +790,14 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) { - if !assert.NoError(t, err, msgAndArgs...) { - t.FailNow() + if assert.NoError(t, err, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NoErrorf asserts that a function returned no error (i.e. `nil`). @@ -628,12 +806,14 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) { // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { - if !assert.NoErrorf(t, err, msg, args...) { - t.FailNow() + if assert.NoErrorf(t, err, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -642,12 +822,14 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") -// -// Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if !assert.NotContains(t, s, contains, msgAndArgs...) { - t.FailNow() + if assert.NotContains(t, s, contains, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -656,12 +838,14 @@ func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ... // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if !assert.NotContainsf(t, s, contains, msg, args...) { - t.FailNow() + if assert.NotContainsf(t, s, contains, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either @@ -670,12 +854,14 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.NotEmpty(t, object, msgAndArgs...) { - t.FailNow() + if assert.NotEmpty(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either @@ -684,296 +870,358 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.NotEmptyf(t, object, msg, args...) { - t.FailNow() + if assert.NotEmptyf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.NotEqual(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.NotEqual(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEqualf asserts that the specified values are NOT equal. // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.NotEqualf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.NotEqualf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) -// -// Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.NotNil(t, object, msgAndArgs...) { - t.FailNow() + if assert.NotNil(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.NotNilf(t, object, msg, args...) { - t.FailNow() + if assert.NotNilf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) -// -// Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.NotPanics(t, f, msgAndArgs...) { - t.FailNow() + if assert.NotPanics(t, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.NotPanicsf(t, f, msg, args...) { - t.FailNow() + if assert.NotPanicsf(t, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if !assert.NotRegexp(t, rx, str, msgAndArgs...) { - t.FailNow() + if assert.NotRegexp(t, rx, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotRegexpf asserts that a specified regexp does not match a string. // // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if !assert.NotRegexpf(t, rx, str, msg, args...) { - t.FailNow() + if assert.NotRegexpf(t, rx, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotSubset asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if !assert.NotSubset(t, list, subset, msgAndArgs...) { - t.FailNow() + if assert.NotSubset(t, list, subset, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotSubsetf asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if !assert.NotSubsetf(t, list, subset, msg, args...) { - t.FailNow() + if assert.NotSubsetf(t, list, subset, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } -// NotZero asserts that i is not the zero value for its type and returns the truth. +// NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if !assert.NotZero(t, i, msgAndArgs...) { - t.FailNow() + if assert.NotZero(t, i, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } -// NotZerof asserts that i is not the zero value for its type and returns the truth. +// NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if !assert.NotZerof(t, i, msg, args...) { - t.FailNow() + if assert.NotZerof(t, i, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.Panics(t, f, msgAndArgs...) { - t.FailNow() + if assert.Panics(t, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.PanicsWithValue(t, expected, f, msgAndArgs...) { - t.FailNow() + if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.PanicsWithValuef(t, expected, f, msg, args...) { - t.FailNow() + if assert.PanicsWithValuef(t, expected, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.Panicsf(t, f, msg, args...) { - t.FailNow() + if assert.Panicsf(t, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if !assert.Regexp(t, rx, str, msgAndArgs...) { - t.FailNow() + if assert.Regexp(t, rx, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if !assert.Regexpf(t, rx, str, msg, args...) { - t.FailNow() + if assert.Regexpf(t, rx, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Subset asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if !assert.Subset(t, list, subset, msgAndArgs...) { - t.FailNow() + if assert.Subset(t, list, subset, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Subsetf asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if !assert.Subsetf(t, list, subset, msg, args...) { - t.FailNow() + if assert.Subsetf(t, list, subset, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // True asserts that the specified value is true. // // assert.True(t, myBool) -// -// Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) { - if !assert.True(t, value, msgAndArgs...) { - t.FailNow() + if assert.True(t, value, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func Truef(t TestingT, value bool, msg string, args ...interface{}) { - if !assert.Truef(t, value, msg, args...) { - t.FailNow() + if assert.Truef(t, value, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -// -// Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if !assert.WithinDurationf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } -// Zero asserts that i is the zero value for its type and returns the truth. +// Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if !assert.Zero(t, i, msgAndArgs...) { - t.FailNow() + if assert.Zero(t, i, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } -// Zerof asserts that i is the zero value for its type and returns the truth. +// Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if !assert.Zerof(t, i, msg, args...) { - t.FailNow() + if assert.Zerof(t, i, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl index d2c38f6..6ffc751 100644 --- a/vendor/github.com/stretchr/testify/require/require.go.tmpl +++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl @@ -1,6 +1,6 @@ {{.Comment}} func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { - if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { - t.FailNow() - } + if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } + if h, ok := t.(tHelper); ok { h.Helper() } + t.FailNow() } diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 7694085..9fe41db 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -14,11 +14,17 @@ import ( // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Conditionf(a.t, comp, msg, args...) } @@ -28,9 +34,10 @@ func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...inte // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Contains(a.t, s, contains, msgAndArgs...) } @@ -40,19 +47,26 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } DirExistsf(a.t, path, msg, args...) } @@ -60,10 +74,11 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])) -// -// Returns whether the assertion was successful (true) or not (false). +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } ElementsMatch(a.t, listA, listB, msgAndArgs...) } @@ -71,10 +86,11 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) -// -// Returns whether the assertion was successful (true) or not (false). +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } ElementsMatchf(a.t, listA, listB, msg, args...) } @@ -82,9 +98,10 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // a slice or a channel with len == 0. // // a.Empty(obj) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Empty(a.t, object, msgAndArgs...) } @@ -92,9 +109,10 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Emptyf(a.t, object, msg, args...) } @@ -102,12 +120,13 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // // a.Equal(123, 123) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Equal(a.t, expected, actual, msgAndArgs...) } @@ -116,9 +135,10 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualError(a.t, theError, errString, msgAndArgs...) } @@ -127,9 +147,10 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualErrorf(a.t, theError, errString, msg, args...) } @@ -137,9 +158,10 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a // and equal. // // a.EqualValues(uint32(123), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualValues(a.t, expected, actual, msgAndArgs...) } @@ -147,9 +169,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn // and equal. // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualValuesf(a.t, expected, actual, msg, args...) } @@ -157,12 +180,13 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // // a.Equalf(123, 123, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Equalf(a.t, expected, actual, msg, args...) } @@ -172,9 +196,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // if a.Error(err) { // assert.Equal(t, expectedError, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Error(a.t, err, msgAndArgs...) } @@ -184,115 +209,150 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Errorf(a.t, err, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } @@ -302,6 +362,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPError(a.t, handler, method, url, values, msgAndArgs...) } @@ -311,6 +374,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPErrorf(a.t, handler, method, url, values, msg, args...) } @@ -320,6 +386,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } @@ -329,6 +398,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } @@ -338,6 +410,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } @@ -347,6 +422,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } @@ -354,6 +432,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Implements(a.t, interfaceObject, object, msgAndArgs...) } @@ -361,96 +442,129 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } JSONEqf(a.t, expected, actual, msg, args...) } @@ -458,9 +572,10 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Len(a.t, object, length, msgAndArgs...) } @@ -468,27 +583,30 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Lenf(a.t, object, length, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Nilf(a.t, object, msg, args...) } @@ -498,9 +616,10 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NoError(a.t, err, msgAndArgs...) } @@ -510,9 +629,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NoErrorf(a.t, err, msg, args...) } @@ -522,9 +642,10 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotContains(a.t, s, contains, msgAndArgs...) } @@ -534,9 +655,10 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotContainsf(a.t, s, contains, msg, args...) } @@ -546,9 +668,10 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEmpty(a.t, object, msgAndArgs...) } @@ -558,9 +681,10 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEmptyf(a.t, object, msg, args...) } @@ -568,11 +692,12 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // // a.NotEqual(obj1, obj2) // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEqual(a.t, expected, actual, msgAndArgs...) } @@ -580,47 +705,52 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // -// Returns whether the assertion was successful (true) or not (false). -// // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEqualf(a.t, expected, actual, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotPanicsf(a.t, f, msg, args...) } @@ -628,9 +758,10 @@ func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...inte // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotRegexp(a.t, rx, str, msgAndArgs...) } @@ -638,9 +769,10 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotRegexpf(a.t, rx, str, msg, args...) } @@ -648,9 +780,10 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // elements given in the specified subset(array, slice...). // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotSubset(a.t, list, subset, msgAndArgs...) } @@ -658,28 +791,36 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs // elements given in the specified subset(array, slice...). // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotSubsetf(a.t, list, subset, msg, args...) } -// NotZero asserts that i is not the zero value for its type and returns the truth. +// NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotZero(a.t, i, msgAndArgs...) } -// NotZerof asserts that i is not the zero value for its type and returns the truth. +// NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Panics(a.t, f, msgAndArgs...) } @@ -687,9 +828,10 @@ func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } PanicsWithValue(a.t, expected, f, msgAndArgs...) } @@ -697,18 +839,20 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFun // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Panicsf(a.t, f, msg, args...) } @@ -716,9 +860,10 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Regexp(a.t, rx, str, msgAndArgs...) } @@ -726,9 +871,10 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Regexpf(a.t, rx, str, msg, args...) } @@ -736,9 +882,10 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // elements given in the specified subset(array, slice...). // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Subset(a.t, list, subset, msgAndArgs...) } @@ -746,54 +893,65 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... // elements given in the specified subset(array, slice...). // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } WithinDurationf(a.t, expected, actual, delta, msg, args...) } -// Zero asserts that i is the zero value for its type and returns the truth. +// Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Zero(a.t, i, msgAndArgs...) } -// Zerof asserts that i is the zero value for its type and returns the truth. +// Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Zerof(a.t, i, msg, args...) } diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl index b93569e..54124df 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl +++ b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl @@ -1,4 +1,5 @@ {{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { + if h, ok := a.t.(tHelper); ok { h.Helper() } {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go index e404f01..690583a 100644 --- a/vendor/github.com/stretchr/testify/require/requirements.go +++ b/vendor/github.com/stretchr/testify/require/requirements.go @@ -6,4 +6,24 @@ type TestingT interface { FailNow() } +type tHelper interface { + Helper() +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) + +// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) + //go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/require/requirements_test.go b/vendor/github.com/stretchr/testify/require/requirements_test.go index d2ccc99..39467d9 100644 --- a/vendor/github.com/stretchr/testify/require/requirements_test.go +++ b/vendor/github.com/stretchr/testify/require/requirements_test.go @@ -1,6 +1,7 @@ package require import ( + "encoding/json" "errors" "testing" "time" @@ -367,3 +368,199 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { t.Error("Check should fail") } } + +func ExampleComparisonAssertionFunc() { + t := &testing.T{} // provided by test + + adder := func(x, y int) int { + return x + y + } + + type args struct { + x int + y int + } + + tests := []struct { + name string + args args + expect int + assertion ComparisonAssertionFunc + }{ + {"2+2=4", args{2, 2}, 4, Equal}, + {"2+2!=5", args{2, 2}, 5, NotEqual}, + {"2+3==5", args{2, 3}, 5, Exactly}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) + }) + } +} + +func TestComparisonAssertionFunc(t *testing.T) { + type iface interface { + Name() string + } + + tests := []struct { + name string + expect interface{} + got interface{} + assertion ComparisonAssertionFunc + }{ + {"implements", (*iface)(nil), t, Implements}, + {"isType", (*testing.T)(nil), t, IsType}, + {"equal", t, t, Equal}, + {"equalValues", t, t, EqualValues}, + {"exactly", t, t, Exactly}, + {"notEqual", t, nil, NotEqual}, + {"notContains", []int{1, 2, 3}, 4, NotContains}, + {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, + {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, + {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, + {"regexp", "^t.*y$", "testify", Regexp}, + {"notRegexp", "^t.*y$", "Testify", NotRegexp}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.expect, tt.got) + }) + } +} + +func ExampleValueAssertionFunc() { + t := &testing.T{} // provided by test + + dumbParse := func(input string) interface{} { + var x interface{} + json.Unmarshal([]byte(input), &x) + return x + } + + tests := []struct { + name string + arg string + assertion ValueAssertionFunc + }{ + {"true is not nil", "true", NotNil}, + {"empty string is nil", "", Nil}, + {"zero is not nil", "0", NotNil}, + {"zero is zero", "0", Zero}, + {"false is zero", "false", Zero}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, dumbParse(tt.arg)) + }) + } +} + +func TestValueAssertionFunc(t *testing.T) { + tests := []struct { + name string + value interface{} + assertion ValueAssertionFunc + }{ + {"notNil", true, NotNil}, + {"nil", nil, Nil}, + {"empty", []int{}, Empty}, + {"notEmpty", []int{1}, NotEmpty}, + {"zero", false, Zero}, + {"notZero", 42, NotZero}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.value) + }) + } +} + +func ExampleBoolAssertionFunc() { + t := &testing.T{} // provided by test + + isOkay := func(x int) bool { + return x >= 42 + } + + tests := []struct { + name string + arg int + assertion BoolAssertionFunc + }{ + {"-1 is bad", -1, False}, + {"42 is good", 42, True}, + {"41 is bad", 41, False}, + {"45 is cool", 45, True}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, isOkay(tt.arg)) + }) + } +} + +func TestBoolAssertionFunc(t *testing.T) { + tests := []struct { + name string + value bool + assertion BoolAssertionFunc + }{ + {"true", true, True}, + {"false", false, False}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.value) + }) + } +} + +func ExampleErrorAssertionFunc() { + t := &testing.T{} // provided by test + + dumbParseNum := func(input string, v interface{}) error { + return json.Unmarshal([]byte(input), v) + } + + tests := []struct { + name string + arg string + assertion ErrorAssertionFunc + }{ + {"1.2 is number", "1.2", NoError}, + {"1.2.3 not number", "1.2.3", Error}, + {"true is not number", "true", Error}, + {"3 is number", "3", NoError}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var x float64 + tt.assertion(t, dumbParseNum(tt.arg, &x)) + }) + } +} + +func TestErrorAssertionFunc(t *testing.T) { + tests := []struct { + name string + err error + assertion ErrorAssertionFunc + }{ + {"noError", nil, NoError}, + {"error", errors.New("whoops"), Error}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.assertion(t, tt.err) + }) + } +} diff --git a/vendor/github.com/xeipuuv/gojsonpointer/README.md b/vendor/github.com/xeipuuv/gojsonpointer/README.md index dbe4d50..0005924 100644 --- a/vendor/github.com/xeipuuv/gojsonpointer/README.md +++ b/vendor/github.com/xeipuuv/gojsonpointer/README.md @@ -1,6 +1,39 @@ # gojsonpointer An implementation of JSON Pointer - Go language +## Usage + jsonText := `{ + "name": "Bobby B", + "occupation": { + "title" : "King", + "years" : 15, + "heir" : "Joffrey B" + } + }` + + var jsonDocument map[string]interface{} + json.Unmarshal([]byte(jsonText), &jsonDocument) + + //create a JSON pointer + pointerString := "/occupation/title" + pointer, _ := NewJsonPointer(pointerString) + + //SET a new value for the "title" in the document + pointer.Set(jsonDocument, "Supreme Leader of Westeros") + + //GET the new "title" from the document + title, _, _ := pointer.Get(jsonDocument) + fmt.Println(title) //outputs "Supreme Leader of Westeros" + + //DELETE the "heir" from the document + deletePointer := NewJsonPointer("/occupation/heir") + deletePointer.Delete(jsonDocument) + + b, _ := json.Marshal(jsonDocument) + fmt.Println(string(b)) + //outputs `{"name":"Bobby B","occupation":{"title":"Supreme Leader of Westeros","years":15}}` + + ## References http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 diff --git a/vendor/github.com/xeipuuv/gojsonpointer/pointer.go b/vendor/github.com/xeipuuv/gojsonpointer/pointer.go index 06f1918..7faf5d7 100644 --- a/vendor/github.com/xeipuuv/gojsonpointer/pointer.go +++ b/vendor/github.com/xeipuuv/gojsonpointer/pointer.go @@ -90,6 +90,13 @@ func (p *JsonPointer) Set(document interface{}, value interface{}) (interface{}, } +// Uses the pointer to delete a value from a JSON document +func (p *JsonPointer) Delete(document interface{}) (interface{}, error) { + is := &implStruct{mode: "DEL", inDocument: document} + p.implementation(is) + return document, is.outError +} + // Both Get and Set functions use the same implementation to avoid code duplication func (p *JsonPointer) implementation(i *implStruct) { @@ -106,9 +113,14 @@ func (p *JsonPointer) implementation(i *implStruct) { node := i.inDocument + previousNodes := make([]interface{}, len(p.referenceTokens)) + previousTokens := make([]string, len(p.referenceTokens)) + for ti, token := range p.referenceTokens { isLastToken := ti == len(p.referenceTokens)-1 + previousNodes[ti] = node + previousTokens[ti] = token switch v := node.(type) { @@ -118,7 +130,11 @@ func (p *JsonPointer) implementation(i *implStruct) { node = v[decodedToken] if isLastToken && i.mode == "SET" { v[decodedToken] = i.setInValue + } else if isLastToken && i.mode =="DEL" { + delete(v,decodedToken) } + } else if (isLastToken && i.mode == "SET") { + v[decodedToken] = i.setInValue } else { i.outError = fmt.Errorf("Object has no key '%s'", decodedToken) i.getOutKind = reflect.Map @@ -144,6 +160,11 @@ func (p *JsonPointer) implementation(i *implStruct) { node = v[tokenIndex] if isLastToken && i.mode == "SET" { v[tokenIndex] = i.setInValue + } else if isLastToken && i.mode =="DEL" { + v[tokenIndex] = v[len(v)-1] + v[len(v)-1] = nil + v = v[:len(v)-1] + previousNodes[ti-1].(map[string]interface{})[previousTokens[ti-1]] = v } default: diff --git a/vendor/github.com/xeipuuv/gojsonpointer/pointer_test.go b/vendor/github.com/xeipuuv/gojsonpointer/pointer_test.go index 9e66d51..612f76e 100644 --- a/vendor/github.com/xeipuuv/gojsonpointer/pointer_test.go +++ b/vendor/github.com/xeipuuv/gojsonpointer/pointer_test.go @@ -245,3 +245,103 @@ func TestSetNode(t *testing.T) { } } + +func TestSetEmptyNode(t *testing.T) { + + jsonText := `{}` + + var jsonDocument interface{} + json.Unmarshal([]byte(jsonText), &jsonDocument) + + in := "/a" + + p, err := NewJsonPointer(in) + if err != nil { + t.Errorf("NewJsonPointer(%v) error %v", in, err.Error()) + } + + _, err = p.Set(jsonDocument, 999) + if err != nil { + t.Errorf("Set(%v) error %v", in, err.Error()) + } + + firstNode := jsonDocument.(map[string]interface{}) + target := firstNode["a"].(int) + if target != 999 { + t.Errorf("Set(%s) failed", in) + } +} + +func TestDelObject(t *testing.T) { + jsonText := `{ + "a":["apple sauce", "ketchup", "soy sauce"], + "d": { + "z" : { + "v" : { + "name" : "donald mcbobble", + "occupation" : "corporate overlord" + } + } + } + }` + + var jsonDocument map[string]interface{} + json.Unmarshal([]byte(jsonText), &jsonDocument) + + //Deleting an object key + in := "/d/z/v/occupation" + p, err := NewJsonPointer(in) + if err != nil { + t.Errorf("NewJsonPointer(%v) error %v", in, err.Error()) + } + + _, err = p.Delete(jsonDocument) + if err != nil { + t.Errorf("Delete(%v) error %v", in, err.Error()) + } + + var d map[string]interface{} = jsonDocument["d"].(map[string]interface{}) + var z map[string]interface{} = d["z"].(map[string]interface{}) + var v map[string]interface{} = z["v"].(map[string]interface{}) + + if _, present := v["occupation"]; present { + t.Errorf("Delete (%s) failed: key is still present in the map", in) + } +} + + +func TestDelArray(t *testing.T) { + jsonText := `{ + "a":["applesauce", "ketchup", "soysauce", "oliveoil"], + "d": { + "z" : { + "v" : { + "name" : "donald mcbobble", + "occupation" : "corporate overlord", + "responsibilities" : ["managing", "hiring"] + } + } + } + }` + + var jsonDocument map[string]interface{} + json.Unmarshal([]byte(jsonText), &jsonDocument) + + //Deleting an array member + in := "/a/2" + p, err := NewJsonPointer(in) + if err != nil { + t.Errorf("NewJsonPointer(%v) error %v", in, err.Error()) + } + + _, err = p.Delete(jsonDocument) + if err != nil { + t.Errorf("Delete(%v) error %v", in, err.Error()) + } + + a := jsonDocument["a"].([]interface{}) + if len(a) != 3 || a[2] == "soysauce" { + t.Errorf("Delete(%v) error (%s)", in, a) + } + +} diff --git a/vendor/github.com/xeipuuv/gojsonreference/reference.go b/vendor/github.com/xeipuuv/gojsonreference/reference.go index d4d2eca..6457291 100644 --- a/vendor/github.com/xeipuuv/gojsonreference/reference.go +++ b/vendor/github.com/xeipuuv/gojsonreference/reference.go @@ -27,11 +27,12 @@ package gojsonreference import ( "errors" - "github.com/xeipuuv/gojsonpointer" "net/url" "path/filepath" "runtime" "strings" + + "github.com/xeipuuv/gojsonpointer" ) const ( @@ -124,16 +125,21 @@ func (r *JsonReference) parse(jsonReferenceString string) (err error) { // Creates a new reference from a parent and a child // If the child cannot inherit from the parent, an error is returned func (r *JsonReference) Inherits(child JsonReference) (*JsonReference, error) { - childUrl := child.GetUrl() - parentUrl := r.GetUrl() - if childUrl == nil { + if child.GetUrl() == nil { return nil, errors.New("childUrl is nil!") } - if parentUrl == nil { + + if r.GetUrl() == nil { return nil, errors.New("parentUrl is nil!") } - ref, err := NewJsonReference(parentUrl.ResolveReference(childUrl).String()) + // Get a copy of the parent url to make sure we do not modify the original. + // URL reference resolving fails if the fragment of the child is empty, but the parent's is not. + // The fragment of the child must be used, so the fragment of the parent is manually removed. + parentUrl := *r.GetUrl() + parentUrl.Fragment = "" + + ref, err := NewJsonReference(parentUrl.ResolveReference(child.GetUrl()).String()) if err != nil { return nil, err } diff --git a/vendor/github.com/xeipuuv/gojsonreference/reference_test.go b/vendor/github.com/xeipuuv/gojsonreference/reference_test.go index 4f6e773..7380473 100644 --- a/vendor/github.com/xeipuuv/gojsonreference/reference_test.go +++ b/vendor/github.com/xeipuuv/gojsonreference/reference_test.go @@ -245,6 +245,24 @@ func TestInheritsDifferentHost(t *testing.T) { } } +func TestInheritsEmptyFragment(t *testing.T) { + in1 := "#a" + in2 := "" + + r1, _ := NewJsonReference(in1) + r2, _ := NewJsonReference(in2) + + result, err := r1.Inherits(r2) + + if err != nil { + t.Errorf("Inherits(%s,%s) should not fail. Error: %s", r1.String(), r2.String(), err.Error()) + } + + if result.String() != in2 { + t.Errorf("Inherits(%s,%s) should be empty but is %s", in1, in2, result) + } +} + func TestFileScheme(t *testing.T) { in1 := "file:///Users/mac/1.json#a" @@ -266,7 +284,7 @@ func TestFileScheme(t *testing.T) { } if r1.IsCanonical() != true { - t.Errorf("NewJsonReference(%v)::IsCanonical %v expect %v", in1, r1.IsCanonical, true) + t.Errorf("NewJsonReference(%v)::IsCanonical %v expect %v", in1, r1.IsCanonical(), true) } result, err := r1.Inherits(r2) diff --git a/vendor/github.com/xeipuuv/gojsonschema/.gitignore b/vendor/github.com/xeipuuv/gojsonschema/.gitignore index c1e0636..68e993c 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/.gitignore +++ b/vendor/github.com/xeipuuv/gojsonschema/.gitignore @@ -1 +1,3 @@ *.sw[nop] +*.iml +.vscode/ diff --git a/vendor/github.com/xeipuuv/gojsonschema/.travis.yml b/vendor/github.com/xeipuuv/gojsonschema/.travis.yml index 9cc01e8..37ec167 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/.travis.yml +++ b/vendor/github.com/xeipuuv/gojsonschema/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - 1.3 + - 1.5 before_install: - - go get github.com/sigu-399/gojsonreference - - go get github.com/sigu-399/gojsonpointer + - go get github.com/xeipuuv/gojsonreference + - go get github.com/xeipuuv/gojsonpointer - go get github.com/stretchr/testify/assert diff --git a/vendor/github.com/xeipuuv/gojsonschema/README.md b/vendor/github.com/xeipuuv/gojsonschema/README.md index fe43659..b890eee 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/README.md +++ b/vendor/github.com/xeipuuv/gojsonschema/README.md @@ -5,7 +5,7 @@ ## Description -An implementation of JSON Schema, based on IETF's draft v4 - Go language +An implementation of JSON Schema for the Go programming language. Supports draft-04, draft-06 and draft-07. References : @@ -156,7 +156,9 @@ The library handles string error codes which you can customize by creating your gojsonschema.Locale = YourCustomLocale{} ``` -However, each error contains additional contextual information. +However, each error contains additional contextual information. + +Newer versions of `gojsonschema` may have new additional errors, so code that uses a custom locale will need to be updated when this happens. **err.Type()**: *string* Returns the "type" of error that occurred. Note you can also type check. See below @@ -170,15 +172,18 @@ Note: An error of RequiredType has an err.Type() return value of "required" "number_not": NumberNotError "missing_dependency": MissingDependencyError "internal": InternalError + "const": ConstEror "enum": EnumError "array_no_additional_items": ArrayNoAdditionalItemsError "array_min_items": ArrayMinItemsError "array_max_items": ArrayMaxItemsError "unique": ItemsMustBeUniqueError + "contains" : ArrayContainsError "array_min_properties": ArrayMinPropertiesError "array_max_properties": ArrayMaxPropertiesError "additional_property_not_allowed": AdditionalPropertyNotAllowedError "invalid_property_pattern": InvalidPropertyPatternError + "invalid_property_name": InvalidPropertyNameError "string_gte": StringLengthGTEError "string_lte": StringLengthLTEError "pattern": DoesNotMatchPatternError @@ -190,12 +195,14 @@ Note: An error of RequiredType has an err.Type() return value of "required" **err.Value()**: *interface{}* Returns the value given -**err.Context()**: *gojsonschema.jsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName +**err.Context()**: *gojsonschema.JsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName **err.Field()**: *string* Returns the fieldname in the format firstName, or for embedded properties, person.firstName. This returns the same as the String() method on *err.Context()* but removes the (root). prefix. **err.Description()**: *string* The error description. This is based on the locale you are using. See the beginning of this section for overwriting the locale with a custom implementation. +**err.DescriptionFormat()**: *string* The error description format. This is relevant if you are adding custom validation errors afterwards to the result. + **err.Details()**: *gojsonschema.ErrorDetails* Returns a map[string]interface{} of additional error details specific to the error. For example, GTE errors will have a "min" value, LTE will have a "max" value. See errors.go for a full description of all the error details. Every error always contains a "field" key that holds the value of *err.Field()* Note in most cases, the err.Details() will be used to generate replacement strings in your locales, and not used directly. These strings follow the text/template format i.e. @@ -229,7 +236,7 @@ JSON Schema allows for optional "format" property to validate instances against ````json {"type": "string", "format": "email"} ```` -Available formats: date-time, hostname, email, ipv4, ipv6, uri, uri-reference. +Available formats: date-time, hostname, email, ipv4, ipv6, uri, uri-reference, uuid, regex. Some of the new formats in draft-06 and draft-07 are not yet implemented. For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this: @@ -286,7 +293,56 @@ func (f ValidUserIdFormatChecker) IsFormat(input interface{}) bool { gojsonschema.FormatCheckers.Add("ValidUserId", ValidUserIdFormatChecker{}) ```` +## Additional custom validation +After the validation has run and you have the results, you may add additional +errors using `Result.AddError`. This is useful to maintain the same format within the resultset instead +of having to add special exceptions for your own errors. Below is an example. +```go +type AnswerInvalidError struct { + gojsonschema.ResultErrorFields +} + +func newAnswerInvalidError(context *gojsonschema.JsonContext, value interface{}, details gojsonschema.ErrorDetails) *AnswerInvalidError { + err := AnswerInvalidError{} + err.SetContext(context) + err.SetType("custom_invalid_error") + // it is important to use SetDescriptionFormat() as this is used to call SetDescription() after it has been parsed + // using the description of err will be overridden by this. + err.SetDescriptionFormat("Answer to the Ultimate Question of Life, the Universe, and Everything is {{.answer}}") + err.SetValue(value) + err.SetDetails(details) + + return &err +} + +func main() { + // ... + schema, err := gojsonschema.NewSchema(schemaLoader) + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + + if true { // some validation + jsonContext := gojsonschema.NewJsonContext("question", nil) + errDetail := gojsonschema.ErrorDetails{ + "answer": 42, + } + result.AddError( + newAnswerInvalidError( + gojsonschema.NewJsonContext("answer", jsonContext), + 52, + errDetail, + ), + errDetail, + ) + } + + return result, err + +} +``` + +This is especially useful if you want to add validation beyond what the +json schema drafts can provide such business specific logic. ## Uses diff --git a/vendor/github.com/xeipuuv/gojsonschema/errors.go b/vendor/github.com/xeipuuv/gojsonschema/errors.go index d39f019..2f326a2 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/errors.go +++ b/vendor/github.com/xeipuuv/gojsonschema/errors.go @@ -56,6 +56,11 @@ type ( ResultErrorFields } + // ConstError. ErrorDetails: allowed + ConstError struct { + ResultErrorFields + } + // EnumError. ErrorDetails: allowed EnumError struct { ResultErrorFields @@ -81,6 +86,11 @@ type ( ResultErrorFields } + // ArrayContainsError. ErrorDetails: + ArrayContainsError struct { + ResultErrorFields + } + // ArrayMinPropertiesError. ErrorDetails: min ArrayMinPropertiesError struct { ResultErrorFields @@ -101,6 +111,11 @@ type ( ResultErrorFields } + // InvalidPopertyNameError. ErrorDetails: property + InvalidPropertyNameError struct { + ResultErrorFields + } + // StringLengthGTEError. ErrorDetails: min StringLengthGTEError struct { ResultErrorFields @@ -145,10 +160,20 @@ type ( NumberLTError struct { ResultErrorFields } + + // ConditionThenError. ErrorDetails: - + ConditionThenError struct { + ResultErrorFields + } + + // ConditionElseError. ErrorDetails: - + ConditionElseError struct { + ResultErrorFields + } ) // newError takes a ResultError type and sets the type, context, description, details, value, and field -func newError(err ResultError, context *jsonContext, value interface{}, locale locale, details ErrorDetails) { +func newError(err ResultError, context *JsonContext, value interface{}, locale locale, details ErrorDetails) { var t string var d string switch err.(type) { @@ -176,6 +201,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l case *InternalError: t = "internal" d = locale.Internal() + case *ConstError: + t = "const" + d = locale.Const() case *EnumError: t = "enum" d = locale.Enum() @@ -191,6 +219,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l case *ItemsMustBeUniqueError: t = "unique" d = locale.Unique() + case *ArrayContainsError: + t = "contains" + d = locale.ArrayContains() case *ArrayMinPropertiesError: t = "array_min_properties" d = locale.ArrayMinProperties() @@ -203,6 +234,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l case *InvalidPropertyPatternError: t = "invalid_property_pattern" d = locale.InvalidPropertyPattern() + case *InvalidPropertyNameError: + t = "invalid_property_name" + d = locale.InvalidPropertyName() case *StringLengthGTEError: t = "string_gte" d = locale.StringGTE() @@ -230,19 +264,26 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l case *NumberLTError: t = "number_lt" d = locale.NumberLT() + case *ConditionThenError: + t = "condition_then" + d = locale.ConditionThen() + case *ConditionElseError: + t = "condition_else" + d = locale.ConditionElse() } err.SetType(t) err.SetContext(context) err.SetValue(value) err.SetDetails(details) + err.SetDescriptionFormat(d) details["field"] = err.Field() if _, exists := details["context"]; !exists && context != nil { details["context"] = context.String() } - err.SetDescription(formatErrorDescription(d, details)) + err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details)) } // formatErrorDescription takes a string in the default text/template diff --git a/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go b/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go index c6a0792..20ead1f 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go +++ b/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go @@ -72,15 +72,15 @@ var ( // so library users can add custom formatters FormatCheckers = FormatCheckerChain{ formatters: map[string]FormatChecker{ - "date-time": DateTimeFormatChecker{}, - "hostname": HostnameFormatChecker{}, - "email": EmailFormatChecker{}, - "ipv4": IPV4FormatChecker{}, - "ipv6": IPV6FormatChecker{}, - "uri": URIFormatChecker{}, + "date-time": DateTimeFormatChecker{}, + "hostname": HostnameFormatChecker{}, + "email": EmailFormatChecker{}, + "ipv4": IPV4FormatChecker{}, + "ipv6": IPV6FormatChecker{}, + "uri": URIFormatChecker{}, "uri-reference": URIReferenceFormatChecker{}, - "uuid": UUIDFormatChecker{}, - "regex": RegexFormatChecker{}, + "uuid": UUIDFormatChecker{}, + "regex": RegexFormatChecker{}, }, } diff --git a/vendor/github.com/xeipuuv/gojsonschema/glide.yaml b/vendor/github.com/xeipuuv/gojsonschema/glide.yaml index 7aef8c0..ab6fb86 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/glide.yaml +++ b/vendor/github.com/xeipuuv/gojsonschema/glide.yaml @@ -7,6 +7,7 @@ import: - package: github.com/xeipuuv/gojsonreference -- package: github.com/stretchr/testify/assert - version: ^1.1.3 - +testImport: +- package: github.com/stretchr/testify + subpackages: + - assert diff --git a/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go b/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go index fcc8d9d..f40668a 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go +++ b/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go @@ -26,20 +26,20 @@ package gojsonschema import "bytes" -// jsonContext implements a persistent linked-list of strings -type jsonContext struct { +// JsonContext implements a persistent linked-list of strings +type JsonContext struct { head string - tail *jsonContext + tail *JsonContext } -func newJsonContext(head string, tail *jsonContext) *jsonContext { - return &jsonContext{head, tail} +func NewJsonContext(head string, tail *JsonContext) *JsonContext { + return &JsonContext{head, tail} } // String displays the context in reverse. // This plays well with the data structure's persistent nature with // Cons and a json document's tree structure. -func (c *jsonContext) String(del ...string) string { +func (c *JsonContext) String(del ...string) string { byteArr := make([]byte, 0, c.stringLen()) buf := bytes.NewBuffer(byteArr) c.writeStringToBuffer(buf, del) @@ -47,7 +47,7 @@ func (c *jsonContext) String(del ...string) string { return buf.String() } -func (c *jsonContext) stringLen() int { +func (c *JsonContext) stringLen() int { length := 0 if c.tail != nil { length = c.tail.stringLen() + 1 // add 1 for "." @@ -57,7 +57,7 @@ func (c *jsonContext) stringLen() int { return length } -func (c *jsonContext) writeStringToBuffer(buf *bytes.Buffer, del []string) { +func (c *JsonContext) writeStringToBuffer(buf *bytes.Buffer, del []string) { if c.tail != nil { c.tail.writeStringToBuffer(buf, del) diff --git a/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go b/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go index a77a81e..5557025 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go +++ b/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go @@ -38,7 +38,6 @@ import ( "runtime" "strings" - "github.com/xeipuuv/gojsonreference" ) @@ -139,13 +138,11 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) { if reference.HasFileScheme { - filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1) + filename := strings.TrimPrefix(refToUrl.String(), "file://") if runtime.GOOS == "windows" { // on Windows, a file URL may have an extra leading slash, use slashes // instead of backslashes, and have spaces escaped - if strings.HasPrefix(filename, "/") { - filename = filename[1:] - } + filename = strings.TrimPrefix(filename, "/") filename = filepath.FromSlash(filename) } @@ -324,6 +321,30 @@ func (l *jsonIOLoader) LoaderFactory() JSONLoaderFactory { return &DefaultJSONLoaderFactory{} } +// JSON raw loader +// In case the JSON is already marshalled to interface{} use this loader +// This is used for testing as otherwise there is no guarantee the JSON is marshalled +// "properly" by using https://golang.org/pkg/encoding/json/#Decoder.UseNumber +type jsonRawLoader struct { + source interface{} +} + +func NewRawLoader(source interface{}) *jsonRawLoader { + return &jsonRawLoader{source: source} +} +func (l *jsonRawLoader) JsonSource() interface{} { + return l.source +} +func (l *jsonRawLoader) LoadJSON() (interface{}, error) { + return l.source, nil +} +func (l *jsonRawLoader) JsonReference() (gojsonreference.JsonReference, error) { + return gojsonreference.NewJsonReference("#") +} +func (l *jsonRawLoader) LoaderFactory() JSONLoaderFactory { + return &DefaultJSONLoaderFactory{} +} + func decodeJsonUsingNumber(r io.Reader) (interface{}, error) { var document interface{} @@ -335,7 +356,7 @@ func decodeJsonUsingNumber(r io.Reader) (interface{}, error) { if err != nil { return nil, err } - + return document, nil } diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE deleted file mode 100644 index c28adba..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2012 Julian Berman - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_00.json deleted file mode 100644 index 5cb29f9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_00.json +++ /dev/null @@ -1 +0,0 @@ -[null,2,3,4] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_01.json deleted file mode 100644 index 4eb0d32..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_01.json +++ /dev/null @@ -1 +0,0 @@ -[null,2,3,"foo"] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_10.json deleted file mode 100644 index e77ca8d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_10.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3,4,5] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_20.json deleted file mode 100644 index 3a26a2e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_20.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_21.json deleted file mode 100644 index fde6c1d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_21.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3,4] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_30.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_30.json deleted file mode 100644 index e77ca8d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_30.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3,4,5] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_31.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_31.json deleted file mode 100644 index 9f5dd4e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_31.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"bar"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_40.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_40.json deleted file mode 100644 index 327fe85..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/data_40.json +++ /dev/null @@ -1 +0,0 @@ -[1,"foo",false] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_0.json deleted file mode 100644 index 75a4b7e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalItems":{"type":"integer"},"items":[{}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_1.json deleted file mode 100644 index d5046a9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalItems":false,"items":{}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_2.json deleted file mode 100644 index 6ab20de..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalItems":false,"items":[{},{},{}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_3.json deleted file mode 100644 index f04aaf8..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_3.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalItems":false} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_4.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_4.json deleted file mode 100644 index fff26f8..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalItems/schema_4.json +++ /dev/null @@ -1 +0,0 @@ -{"items":[{"type":"integer"}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_00.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_01.json deleted file mode 100644 index 513d61f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1,"quux":"boom"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_02.json deleted file mode 100644 index 3a26a2e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_02.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_03.json deleted file mode 100644 index 65a158d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1, "vroom": 2} diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_10.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_11.json deleted file mode 100644 index 2129e62..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1,"quux":true} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_12.json deleted file mode 100644 index ce7708b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1,"quux":12} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_20.json deleted file mode 100644 index 2129e62..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/data_20.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1,"quux":true} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_0.json deleted file mode 100644 index 99d0ef4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalProperties":false,"properties":{"bar":{},"foo":{}},"patternProperties": { "^v": {} }} diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_1.json deleted file mode 100644 index b55c092..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalProperties":{"type":"boolean"},"properties":{"bar":{},"foo":{}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_2.json deleted file mode 100644 index 4d0bc3a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/additionalProperties/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"properties":{"bar":{},"foo":{}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_00.json deleted file mode 100644 index 7973c0a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":"baz"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_01.json deleted file mode 100644 index 62aa0a1..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"baz"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_02.json deleted file mode 100644 index 70eef88..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_03.json deleted file mode 100644 index 54c2b0b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":"quux","foo":"baz"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_10.json deleted file mode 100644 index fa13a37..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"baz":null,"foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_11.json deleted file mode 100644 index 366679e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"baz":null,"foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_12.json deleted file mode 100644 index e8f534a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"baz":null} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_13.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_13.json deleted file mode 100644 index 6fbe198..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_13.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_14.json deleted file mode 100644 index 70eef88..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_14.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_20.json deleted file mode 100644 index 410b14d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_20.json +++ /dev/null @@ -1 +0,0 @@ -25 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_21.json deleted file mode 100644 index 597975b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/data_21.json +++ /dev/null @@ -1 +0,0 @@ -35 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_0.json deleted file mode 100644 index 13b607a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"allOf":[{"properties":{"bar":{"type":"integer"}},"required":["bar"]},{"properties":{"foo":{"type":"string"}},"required":["foo"]}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_1.json deleted file mode 100644 index f618c0b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"allOf":[{"properties":{"foo":{"type":"string"}},"required":["foo"]},{"properties":{"baz":{"type":"null"}},"required":["baz"]}],"properties":{"bar":{"type":"integer"}},"required":["bar"]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_2.json deleted file mode 100644 index 748ee7e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/allOf/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"allOf":[{"maximum":30},{"minimum":20}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_00.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_00.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_01.json deleted file mode 100644 index 68151b2..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_01.json +++ /dev/null @@ -1 +0,0 @@ -2.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_02.json deleted file mode 100644 index e440e5c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_02.json +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_03.json deleted file mode 100644 index 400122e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_03.json +++ /dev/null @@ -1 +0,0 @@ -1.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_10.json deleted file mode 100644 index e440e5c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_10.json +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_11.json deleted file mode 100644 index b2bb988..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_11.json +++ /dev/null @@ -1 +0,0 @@ -"foobar" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_12.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/data_12.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_0.json deleted file mode 100644 index 5540cb8..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"anyOf":[{"type":"integer"},{"minimum":2}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_1.json deleted file mode 100644 index cbe387a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/anyOf/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"anyOf":[{"maxLength":2},{"minLength":4}],"type":"string"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_00.json deleted file mode 100644 index fc7a98b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"definitions":{"foo":{"type":"integer"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_10.json deleted file mode 100644 index 5270def..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"definitions":{"foo":{"type":1}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_0.json deleted file mode 100644 index 412c216..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_1.json deleted file mode 100644 index 412c216..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/definitions/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_00.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_01.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_02.json deleted file mode 100644 index b0fcefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_03.json deleted file mode 100644 index 70eef88..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_04.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_04.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_10.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_11.json deleted file mode 100644 index b0fcefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_12.json deleted file mode 100644 index 2c48cfb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1,"quux":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_13.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_13.json deleted file mode 100644 index 6fe283b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_13.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1,"quux":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_14.json deleted file mode 100644 index 7bed583..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_14.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":1,"quux":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_15.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_15.json deleted file mode 100644 index 10d82bf..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_15.json +++ /dev/null @@ -1 +0,0 @@ -{"quux":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_20.json deleted file mode 100644 index b0fcefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_20.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_21.json deleted file mode 100644 index 707f7ce..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_21.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_22.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_22.json deleted file mode 100644 index 6fbe198..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_22.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_23.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_23.json deleted file mode 100644 index a163738..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_23.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":"quux","foo":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_24.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_24.json deleted file mode 100644 index 2fee1e3..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/data_24.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":"quux","foo":"quux"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_0.json deleted file mode 100644 index 445985c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"dependencies":{"bar":["foo"]}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_1.json deleted file mode 100644 index 1bb5a67..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"dependencies":{"quux":["foo","bar"]}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_2.json deleted file mode 100644 index 27f97a4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/dependencies/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"dependencies":{"bar":{"properties":{"bar":{"type":"integer"},"foo":{"type":"integer"}}}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_00.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_00.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_01.json deleted file mode 100644 index bf0d87a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_01.json +++ /dev/null @@ -1 +0,0 @@ -4 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_10.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_10.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_11.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_11.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_12.json deleted file mode 100644 index 1bfa80c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":false} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_0.json deleted file mode 100644 index 240e702..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"enum":[1,2,3]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_1.json deleted file mode 100644 index d6b8c5f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/enum/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"enum":[6,"foo",[],true,{"foo":12}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_00.json deleted file mode 100644 index 60bc259..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_00.json +++ /dev/null @@ -1 +0,0 @@ -"test" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_01.json deleted file mode 100644 index 6d9ec40..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_01.json +++ /dev/null @@ -1 +0,0 @@ -"test@" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_02.json deleted file mode 100644 index 6b8674d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"test@test.com" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_03.json deleted file mode 100644 index 970043c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_03.json +++ /dev/null @@ -1 +0,0 @@ -"AB-10105" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_04.json deleted file mode 100644 index 140843f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_04.json +++ /dev/null @@ -1 +0,0 @@ -"ABC10105" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_05.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_05.json deleted file mode 100644 index e87a8ac..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_05.json +++ /dev/null @@ -1 +0,0 @@ -"05:15:37" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_06.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_06.json deleted file mode 100644 index 17f91eb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_06.json +++ /dev/null @@ -1 +0,0 @@ -"2015-05-13" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_07.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_07.json deleted file mode 100644 index f0218e9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_07.json +++ /dev/null @@ -1 +0,0 @@ -"2015-6-31" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_08.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_08.json deleted file mode 100644 index bf9e258..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_08.json +++ /dev/null @@ -1 +0,0 @@ -"2015-01-30 19:08:06" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_09.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_09.json deleted file mode 100644 index 1a57beb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_09.json +++ /dev/null @@ -1 +0,0 @@ -"18:31:24-05:00" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_10.json deleted file mode 100644 index 00ed4ee..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_10.json +++ /dev/null @@ -1 +0,0 @@ -"2002-10-02T10:00:00-05:00" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_11.json deleted file mode 100644 index a8f92d5..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_11.json +++ /dev/null @@ -1 +0,0 @@ -"2002-10-02T15:00:00Z" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_12.json deleted file mode 100644 index 0975607..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_12.json +++ /dev/null @@ -1 +0,0 @@ -"2002-10-02T15:00:00.05Z" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_14.json deleted file mode 100644 index 15a9a87..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_14.json +++ /dev/null @@ -1 +0,0 @@ -"sub.example.com" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_15.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_15.json deleted file mode 100644 index 5c8e9b7..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_15.json +++ /dev/null @@ -1 +0,0 @@ -"hello.co.uk" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_16.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_16.json deleted file mode 100644 index f5a11ec..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_16.json +++ /dev/null @@ -1 +0,0 @@ -"http://example.com" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_17.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_17.json deleted file mode 100644 index 062bf8c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_17.json +++ /dev/null @@ -1 +0,0 @@ -"example_com" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_18.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_18.json deleted file mode 100644 index fd44410..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_18.json +++ /dev/null @@ -1 +0,0 @@ -"4.2.2.4" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_19.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_19.json deleted file mode 100644 index 1e490c6..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_19.json +++ /dev/null @@ -1 +0,0 @@ -"4.1.1111.45" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_20.json deleted file mode 100644 index 2891810..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_20.json +++ /dev/null @@ -1 +0,0 @@ -"FE80:0000:0000:0000:0202:B3FF:FE1E:8329" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_21.json deleted file mode 100644 index ad20ef3..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_21.json +++ /dev/null @@ -1 +0,0 @@ -"FE80::0202:B3FF:FE1E:8329" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_22.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_22.json deleted file mode 100644 index 97dae8f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_22.json +++ /dev/null @@ -1 +0,0 @@ -"1200::AB00:1234::2552:7777:1313" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_23.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_23.json deleted file mode 100644 index ef38c10..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_23.json +++ /dev/null @@ -1 +0,0 @@ -"1200:0000:AB00:1234:O000:2552:7777:1313" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_24.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_24.json deleted file mode 100644 index 4187b90..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_24.json +++ /dev/null @@ -1 +0,0 @@ -"ftp://ftp.is.co.za/rfc/rfc1808.txt" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_25.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_25.json deleted file mode 100644 index 7816838..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_25.json +++ /dev/null @@ -1 +0,0 @@ -"mailto:john.doe@example.com" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_26.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_26.json deleted file mode 100644 index df1cfae..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_26.json +++ /dev/null @@ -1 +0,0 @@ -"tel:+1-816-555-1212" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_27.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_27.json deleted file mode 100644 index 28995dd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_27.json +++ /dev/null @@ -1 +0,0 @@ -"http://www.ietf.org/rfc/rfc2396.txt" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_28.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_28.json deleted file mode 100644 index 6b620ed..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_28.json +++ /dev/null @@ -1 +0,0 @@ -"example.com/path/to/file" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_29.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_29.json deleted file mode 100644 index f599e28..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_29.json +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_30.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_30.json deleted file mode 100644 index b4de394..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/data_30.json +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_0.json deleted file mode 100644 index b54a202..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "email"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_1.json deleted file mode 100644 index 7df6711..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "invoice"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_2.json deleted file mode 100644 index 0dc4b8f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "date-time"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_3.json deleted file mode 100644 index d1cf1a0..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_3.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "hostname"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_4.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_4.json deleted file mode 100644 index 8468509..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_4.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "ipv4"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_5.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_5.json deleted file mode 100644 index ddee847..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_5.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "ipv6"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_6.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_6.json deleted file mode 100644 index 493546d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_6.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "string", "format": "uri"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_7.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_7.json deleted file mode 100644 index 4743e21..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/format/schema_7.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "number", "format": "evenNumber"} diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_00.json deleted file mode 100644 index 3a26a2e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_00.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_01.json deleted file mode 100644 index 084da97..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_01.json +++ /dev/null @@ -1 +0,0 @@ -[1,"x"] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_02.json deleted file mode 100644 index 9f5dd4e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"bar"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_10.json deleted file mode 100644 index f4e5290..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_10.json +++ /dev/null @@ -1 +0,0 @@ -[1,"foo"] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_11.json deleted file mode 100644 index d68c500..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/data_11.json +++ /dev/null @@ -1 +0,0 @@ -["foo",1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_0.json deleted file mode 100644 index e628c9f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"items":{"type":"integer"}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_1.json deleted file mode 100644 index 8b92516..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/items/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"items":[{"type":"integer"},{"type":"string"}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_00.json deleted file mode 100644 index bace2a0..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_00.json +++ /dev/null @@ -1 +0,0 @@ -[1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_01.json deleted file mode 100644 index 3169929..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_01.json +++ /dev/null @@ -1 +0,0 @@ -[1,2] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_02.json deleted file mode 100644 index 3a26a2e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_02.json +++ /dev/null @@ -1 +0,0 @@ -[1,2,3] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_03.json deleted file mode 100644 index b2bb988..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/data_03.json +++ /dev/null @@ -1 +0,0 @@ -"foobar" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/schema_0.json deleted file mode 100644 index 81cfbcc..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxItems/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"maxItems":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_00.json deleted file mode 100644 index 91d1e39..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_00.json +++ /dev/null @@ -1 +0,0 @@ -"f" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_01.json deleted file mode 100644 index 67af23e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_01.json +++ /dev/null @@ -1 +0,0 @@ -"fo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_02.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_03.json deleted file mode 100644 index 9a03714..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_03.json +++ /dev/null @@ -1 +0,0 @@ -10 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_04.json deleted file mode 100644 index 7d62b4d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/data_04.json +++ /dev/null @@ -1 +0,0 @@ -"世界" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/schema_0.json deleted file mode 100644 index 30a0747..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxLength/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"maxLength":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_00.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_01.json deleted file mode 100644 index b0fcefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_02.json deleted file mode 100644 index bce2e6b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"baz":3,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_03.json deleted file mode 100644 index b2bb988..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/data_03.json +++ /dev/null @@ -1 +0,0 @@ -"foobar" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/schema_0.json deleted file mode 100644 index a9d977b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maxProperties/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"maxProperties":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_00.json deleted file mode 100644 index c20c8ac..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_00.json +++ /dev/null @@ -1 +0,0 @@ -2.6 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_01.json deleted file mode 100644 index 56e972a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_01.json +++ /dev/null @@ -1 +0,0 @@ -3.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_02.json deleted file mode 100644 index 3403a0c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"x" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_10.json deleted file mode 100644 index 6161878..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_10.json +++ /dev/null @@ -1 +0,0 @@ -2.2 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_11.json deleted file mode 100644 index e440e5c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/data_11.json +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_0.json deleted file mode 100644 index e88aefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"maximum":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_1.json deleted file mode 100644 index b96954d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/maximum/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"exclusiveMaximum":true,"maximum":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_00.json deleted file mode 100644 index 3169929..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_00.json +++ /dev/null @@ -1 +0,0 @@ -[1,2] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_01.json deleted file mode 100644 index bace2a0..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_01.json +++ /dev/null @@ -1 +0,0 @@ -[1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_02.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_02.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_03.json deleted file mode 100644 index 3cc762b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/data_03.json +++ /dev/null @@ -1 +0,0 @@ -"" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/schema_0.json deleted file mode 100644 index dcfe1c9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minItems/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"minItems":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_00.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_00.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_01.json deleted file mode 100644 index 67af23e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_01.json +++ /dev/null @@ -1 +0,0 @@ -"fo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_02.json deleted file mode 100644 index 91d1e39..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"f" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_03.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_03.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_04.json deleted file mode 100644 index 62db65a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/data_04.json +++ /dev/null @@ -1 +0,0 @@ -"世" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/schema_0.json deleted file mode 100644 index efc2304..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minLength/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"minLength":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_00.json deleted file mode 100644 index b0fcefd..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":2,"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_01.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_02.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_03.json deleted file mode 100644 index 3cc762b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/data_03.json +++ /dev/null @@ -1 +0,0 @@ -"" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/schema_0.json deleted file mode 100644 index 87b25c2..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minProperties/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"minProperties":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_00.json deleted file mode 100644 index c20c8ac..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_00.json +++ /dev/null @@ -1 +0,0 @@ -2.6 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_01.json deleted file mode 100644 index 490f510..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_01.json +++ /dev/null @@ -1 +0,0 @@ -0.6 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_02.json deleted file mode 100644 index 3403a0c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"x" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_10.json deleted file mode 100644 index ea710ab..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_10.json +++ /dev/null @@ -1 +0,0 @@ -1.2 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_11.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/data_11.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_0.json deleted file mode 100644 index 0acddfc..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"minimum":1.1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_1.json deleted file mode 100644 index e0945a4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/minimum/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"exclusiveMinimum":true,"minimum":1.1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_00.json deleted file mode 100644 index 9a03714..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_00.json +++ /dev/null @@ -1 +0,0 @@ -10 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_01.json deleted file mode 100644 index c793025..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_01.json +++ /dev/null @@ -1 +0,0 @@ -7 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_02.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_10.json deleted file mode 100644 index c227083..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_10.json +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_11.json deleted file mode 100644 index 958d30d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_11.json +++ /dev/null @@ -1 +0,0 @@ -4.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_12.json deleted file mode 100644 index 597975b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_12.json +++ /dev/null @@ -1 +0,0 @@ -35 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_20.json deleted file mode 100644 index 136664f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_20.json +++ /dev/null @@ -1 +0,0 @@ -0.0075 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_21.json deleted file mode 100644 index 77dfb80..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/data_21.json +++ /dev/null @@ -1 +0,0 @@ -0.00751 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_0.json deleted file mode 100644 index b51609f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"multipleOf":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_1.json deleted file mode 100644 index 2ee7966..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"multipleOf":1.5} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_2.json deleted file mode 100644 index de303ef..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/multipleOf/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"multipleOf":0.0001} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_00.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_00.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_01.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_01.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_10.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_10.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_11.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_11.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_12.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_12.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_20.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_20.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_21.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_21.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_22.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_22.json deleted file mode 100644 index 9f5dd4e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/data_22.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"bar"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_0.json deleted file mode 100644 index fc125d7..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"not":{"type":"integer"}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_1.json deleted file mode 100644 index 7f21947..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"not":{"type":["integer","boolean"]}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_2.json deleted file mode 100644 index a3f1680..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/not/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"not":{"properties":{"foo":{"type":"string"}},"type":"object"}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_00.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_00.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_01.json deleted file mode 100644 index 68151b2..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_01.json +++ /dev/null @@ -1 +0,0 @@ -2.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_02.json deleted file mode 100644 index e440e5c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_02.json +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_03.json deleted file mode 100644 index 400122e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_03.json +++ /dev/null @@ -1 +0,0 @@ -1.5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_10.json deleted file mode 100644 index e440e5c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_10.json +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_11.json deleted file mode 100644 index b2bb988..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_11.json +++ /dev/null @@ -1 +0,0 @@ -"foobar" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_12.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/data_12.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_0.json deleted file mode 100644 index 217c51e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"oneOf":[{"type":"integer"},{"minimum":2}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_1.json deleted file mode 100644 index 4dae78a..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/oneOf/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"oneOf":[{"minLength":2},{"maxLength":4}],"type":"string"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_00.json deleted file mode 100644 index a9cf1d4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_00.json +++ /dev/null @@ -1 +0,0 @@ -"aaa" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_01.json deleted file mode 100644 index 4f44a21..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_01.json +++ /dev/null @@ -1 +0,0 @@ -"abc" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_02.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/data_02.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/schema_0.json deleted file mode 100644 index 47a0a0e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/pattern/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"pattern":"^a*$"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_00.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_01.json deleted file mode 100644 index 40129f4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1,"foooooo":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_02.json deleted file mode 100644 index 7a2b52f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"bar","fooooo":2} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_03.json deleted file mode 100644 index e7e5b7c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":"bar","foooooo":"baz"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_04.json deleted file mode 100644 index 3cacc0b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_04.json +++ /dev/null @@ -1 +0,0 @@ -12 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_10.json deleted file mode 100644 index c7b8e69..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"a":21} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_11.json deleted file mode 100644 index 644136d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"aaaa":18} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_12.json deleted file mode 100644 index 4af3999..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"a":21,"aaaa":18} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_13.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_13.json deleted file mode 100644 index 5286d3b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_13.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"bar"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_14.json deleted file mode 100644 index b778e0f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_14.json +++ /dev/null @@ -1 +0,0 @@ -{"aaaa":31} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_15.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_15.json deleted file mode 100644 index 786f9cb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_15.json +++ /dev/null @@ -1 +0,0 @@ -{"aaa":"foo","aaaa":31} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_20.json deleted file mode 100644 index b2ef65b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_20.json +++ /dev/null @@ -1 +0,0 @@ -{"answer 1":"42"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_21.json deleted file mode 100644 index f8f6268..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_21.json +++ /dev/null @@ -1 +0,0 @@ -{"a31b":null} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_22.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_22.json deleted file mode 100644 index bfc72fb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_22.json +++ /dev/null @@ -1 +0,0 @@ -{"a_x_3":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_23.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_23.json deleted file mode 100644 index cd32d32..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_23.json +++ /dev/null @@ -1 +0,0 @@ -{"a_X_3":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_24.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_24.json deleted file mode 100644 index c578f69..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_24.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "a": "hello", - "aaaaaaaaaaaaaaaaaaa": null -} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_25.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_25.json deleted file mode 100644 index dd415e0..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_25.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "aaaaaaaaaaaaaaaaaaa": null -} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_26.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_26.json deleted file mode 100644 index 1b44a9f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/data_26.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dictionary": { - "aaaaaaaaaaaaaaaaaaaa": null, - "b": "hello" - } -} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_0.json deleted file mode 100644 index 6f5a819..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"patternProperties":{"f.*o":{"type":"integer"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_1.json deleted file mode 100644 index 8776f20..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"patternProperties":{"a*":{"type":"integer"},"aaa*":{"maximum":20}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_2.json deleted file mode 100644 index 04a4cbc..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"patternProperties":{"X_":{"type":"string"},"[0-9]{2,}":{"type":"boolean"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_3.json deleted file mode 100644 index 03a67b9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "patternProperties": { - "^[a-zA-Z0-9]{1,10}$": { "type": "string" } - }, - "additionalProperties": false -} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_4.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_4.json deleted file mode 100644 index 4c35adb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/patternProperties/schema_4.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "dictionary": { - "type": "object", - "patternProperties": { - "^[a-zA-Z0-9]{1,10}$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false -} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_00.json deleted file mode 100644 index 022ce23..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":"baz","foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_01.json deleted file mode 100644 index 9ed6220..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":{},"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_02.json deleted file mode 100644 index 00062cc..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":{},"foo":[]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_03.json deleted file mode 100644 index 81ebc36..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"quux":[]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_04.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_04.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_10.json deleted file mode 100644 index a82c153..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":[1,2]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_11.json deleted file mode 100644 index f08510e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":[1,2,3,4]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_12.json deleted file mode 100644 index 2ad6a35..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_12.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":[]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_13.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_13.json deleted file mode 100644 index 13370fe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_13.json +++ /dev/null @@ -1 +0,0 @@ -{"fxo":[1,2]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_14.json deleted file mode 100644 index f82be5d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_14.json +++ /dev/null @@ -1 +0,0 @@ -{"fxo":[]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_15.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_15.json deleted file mode 100644 index 2ed6680..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_15.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":[]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_16.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_16.json deleted file mode 100644 index 935e525..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_16.json +++ /dev/null @@ -1 +0,0 @@ -{"quux":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_17.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_17.json deleted file mode 100644 index 531bbc9..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/data_17.json +++ /dev/null @@ -1 +0,0 @@ -{"quux":"foo"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_0.json deleted file mode 100644 index 2c73cd5..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"properties":{"bar":{"type":"string"},"foo":{"type":"integer"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_1.json deleted file mode 100644 index 144f96e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/properties/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalProperties":{"type":"integer"},"patternProperties":{"f.o":{"minItems":2}},"properties":{"bar":{"type":"array"},"foo":{"maxItems":3,"type":"array"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_00.json deleted file mode 100644 index 1bfa80c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":false} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_01.json deleted file mode 100644 index 27768a4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":{"foo":false}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_02.json deleted file mode 100644 index a274272..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_02.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":false} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_03.json deleted file mode 100644 index 1de6676..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":{"bar":false}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_10.json deleted file mode 100644 index cc6193b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":3} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_11.json deleted file mode 100644 index 7716a93..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_11.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":true} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_20.json deleted file mode 100644 index 3169929..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_20.json +++ /dev/null @@ -1 +0,0 @@ -[1,2] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_21.json deleted file mode 100644 index f4e5290..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_21.json +++ /dev/null @@ -1 +0,0 @@ -[1,"foo"] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_30.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_30.json deleted file mode 100644 index 1606db7..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_30.json +++ /dev/null @@ -1 +0,0 @@ -{"slash":"aoeu"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_31.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_31.json deleted file mode 100644 index 51cdcbc..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_31.json +++ /dev/null @@ -1 +0,0 @@ -{"tilda":"aoeu"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_32.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_32.json deleted file mode 100644 index 1aa03c6..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_32.json +++ /dev/null @@ -1 +0,0 @@ -{"percent":"aoeu"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_40.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_40.json deleted file mode 100644 index 7813681..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_40.json +++ /dev/null @@ -1 +0,0 @@ -5 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_41.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_41.json deleted file mode 100644 index 075c842..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_41.json +++ /dev/null @@ -1 +0,0 @@ -"a" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_50.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_50.json deleted file mode 100644 index 9d936d5..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_50.json +++ /dev/null @@ -1 +0,0 @@ -{"minLength":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_51.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_51.json deleted file mode 100644 index 64ba18b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/data_51.json +++ /dev/null @@ -1 +0,0 @@ -{"minLength":-1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_0.json deleted file mode 100644 index a243138..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"additionalProperties":false,"properties":{"foo":{"$ref":"#"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_1.json deleted file mode 100644 index 5475b8e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"properties":{"bar":{"$ref":"#/properties/foo"},"foo":{"type":"integer"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_2.json deleted file mode 100644 index 80f5a14..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"items":[{"type":"integer"},{"$ref":"#/items/0"}]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_3.json deleted file mode 100644 index 5f5c1e2..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_3.json +++ /dev/null @@ -1 +0,0 @@ -{"percent%field":{"type":"integer"},"properties":{"percent":{"$ref":"#/percent%25field"},"slash":{"$ref":"#/slash~1field"},"tilda":{"$ref":"#/tilda~0field"}},"slash/field":{"type":"integer"},"tilda~field":{"type":"integer"}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_4.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_4.json deleted file mode 100644 index ac40ec7..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_4.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"#/definitions/c","definitions":{"a":{"type":"integer"},"b":{"$ref":"#/definitions/a"},"c":{"$ref":"#/definitions/b"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_5.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_5.json deleted file mode 100644 index 412c216..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_5.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_00.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_00.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_01.json deleted file mode 100644 index 075c842..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_01.json +++ /dev/null @@ -1 +0,0 @@ -"a" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_10.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_10.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_11.json deleted file mode 100644 index 075c842..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_11.json +++ /dev/null @@ -1 +0,0 @@ -"a" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_20.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_20.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_21.json deleted file mode 100644 index 075c842..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_21.json +++ /dev/null @@ -1 +0,0 @@ -"a" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_30.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_30.json deleted file mode 100644 index 89d00ba..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_30.json +++ /dev/null @@ -1 +0,0 @@ -[[1]] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_31.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_31.json deleted file mode 100644 index 294b06e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/data_31.json +++ /dev/null @@ -1 +0,0 @@ -[["a"]] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_0.json deleted file mode 100644 index c9d47df..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://localhost:1234/integer.json"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_1.json deleted file mode 100644 index de9da7f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://localhost:1234/subSchemas.json#/integer"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_2.json deleted file mode 100644 index 40b5213..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"http://localhost:1234/subSchemas.json#/refToInteger"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_3.json deleted file mode 100644 index 51bd33d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/schema_3.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"http://localhost:1234","items":{"id":"folder/","items":{"$ref":"folderInteger.json"}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_00.json deleted file mode 100644 index 2518e68..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_00.json +++ /dev/null @@ -1 +0,0 @@ -{"foo":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_01.json deleted file mode 100644 index ba06f3f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_01.json +++ /dev/null @@ -1 +0,0 @@ -{"bar":1} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_10.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/data_10.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_0.json deleted file mode 100644 index 237ecc4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"properties":{"bar":{},"foo":{}},"required":["foo"]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_1.json deleted file mode 100644 index 5891a51..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/required/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"properties":{"foo":{}}} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_00.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_00.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_01.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_01.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_02.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_02.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_03.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_03.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_04.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_04.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_05.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_05.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_05.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_06.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_06.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_06.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_10.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_10.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_10.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_11.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_11.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_11.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_12.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_12.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_12.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_13.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_13.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_13.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_14.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_14.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_14.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_15.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_15.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_15.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_16.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_16.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_16.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_20.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_20.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_20.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_21.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_21.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_21.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_22.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_22.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_22.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_23.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_23.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_23.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_24.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_24.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_24.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_25.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_25.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_25.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_26.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_26.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_26.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_30.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_30.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_30.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_31.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_31.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_31.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_32.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_32.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_32.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_33.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_33.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_33.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_34.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_34.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_34.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_35.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_35.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_35.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_36.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_36.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_36.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_40.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_40.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_40.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_41.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_41.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_41.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_42.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_42.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_42.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_43.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_43.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_43.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_44.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_44.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_44.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_45.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_45.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_45.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_46.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_46.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_46.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_50.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_50.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_50.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_51.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_51.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_51.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_52.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_52.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_52.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_53.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_53.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_53.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_54.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_54.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_54.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_55.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_55.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_55.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_56.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_56.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_56.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_60.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_60.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_60.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_61.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_61.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_61.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_62.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_62.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_62.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_63.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_63.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_63.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_64.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_64.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_64.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_65.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_65.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_65.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_66.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_66.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_66.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_70.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_70.json deleted file mode 100644 index 56a6051..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_70.json +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_71.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_71.json deleted file mode 100644 index 7e9668e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_71.json +++ /dev/null @@ -1 +0,0 @@ -"foo" \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_72.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_72.json deleted file mode 100644 index b123147..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_72.json +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_73.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_73.json deleted file mode 100644 index 9e26dfe..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_73.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_74.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_74.json deleted file mode 100644 index 0637a08..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_74.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_75.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_75.json deleted file mode 100644 index f32a580..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_75.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_76.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_76.json deleted file mode 100644 index ec747fa..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/data_76.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_0.json deleted file mode 100644 index 2be72ba..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"integer"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_1.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_1.json deleted file mode 100644 index da4eeec..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_1.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"number"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_2.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_2.json deleted file mode 100644 index 4db187e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_2.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"string"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_3.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_3.json deleted file mode 100644 index ffa5c9f..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_3.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"object"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_4.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_4.json deleted file mode 100644 index bc88ff4..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_4.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"array"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_5.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_5.json deleted file mode 100644 index 7763bc5..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_5.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"boolean"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_6.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_6.json deleted file mode 100644 index fedaf46..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_6.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"null"} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_7.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_7.json deleted file mode 100644 index c243f0b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/type/schema_7.json +++ /dev/null @@ -1 +0,0 @@ -{"type":["integer","string"]} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_00.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_00.json deleted file mode 100644 index 3169929..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_00.json +++ /dev/null @@ -1 +0,0 @@ -[1,2] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_01.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_01.json deleted file mode 100644 index a7c0e4b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_01.json +++ /dev/null @@ -1 +0,0 @@ -[1,1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_010.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_010.json deleted file mode 100644 index 7e6261e..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_010.json +++ /dev/null @@ -1 +0,0 @@ -[0,false] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_011.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_011.json deleted file mode 100644 index 48006ce..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_011.json +++ /dev/null @@ -1 +0,0 @@ -[{},[1],true,null,1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_012.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_012.json deleted file mode 100644 index 067faf5..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_012.json +++ /dev/null @@ -1 +0,0 @@ -[{},[1],true,null,{},1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_02.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_02.json deleted file mode 100644 index 2288116..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_02.json +++ /dev/null @@ -1 +0,0 @@ -[1,1,1] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_03.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_03.json deleted file mode 100644 index b7734bb..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_03.json +++ /dev/null @@ -1 +0,0 @@ -[{"foo":"bar"},{"foo":"baz"}] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_04.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_04.json deleted file mode 100644 index 67d501b..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_04.json +++ /dev/null @@ -1 +0,0 @@ -[{"foo":"bar"},{"foo":"bar"}] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_05.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_05.json deleted file mode 100644 index 4e042c2..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_05.json +++ /dev/null @@ -1 +0,0 @@ -[{"foo":{"bar":{"baz":true}}},{"foo":{"bar":{"baz":false}}}] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_06.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_06.json deleted file mode 100644 index 0f63748..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_06.json +++ /dev/null @@ -1 +0,0 @@ -[{"foo":{"bar":{"baz":true}}},{"foo":{"bar":{"baz":true}}}] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_07.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_07.json deleted file mode 100644 index 8318b7d..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_07.json +++ /dev/null @@ -1 +0,0 @@ -[["foo"],["bar"]] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_08.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_08.json deleted file mode 100644 index 15caa6c..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_08.json +++ /dev/null @@ -1 +0,0 @@ -[["foo"],["foo"]] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_09.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_09.json deleted file mode 100644 index 1083d09..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/data_09.json +++ /dev/null @@ -1 +0,0 @@ -[1,true] \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/schema_0.json b/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/schema_0.json deleted file mode 100644 index d598d70..0000000 --- a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/uniqueItems/schema_0.json +++ /dev/null @@ -1 +0,0 @@ -{"uniqueItems":true} \ No newline at end of file diff --git a/vendor/github.com/xeipuuv/gojsonschema/jsonschema_test.go b/vendor/github.com/xeipuuv/gojsonschema/jsonschema_test.go new file mode 100644 index 0000000..baf4910 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/jsonschema_test.go @@ -0,0 +1,131 @@ +// Copyright 2017 johandorland ( https://github.com/johandorland ) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gojsonschema + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "testing" +) + +type jsonSchemaTest struct { + Description string `json:"description"` + // Some tests may not always pass, so some tests are manually edited to include + // an extra attribute whether that specific test should be disabled and skipped + Disabled bool `json:"disabled"` + Schema interface{} `json:"schema"` + Tests []jsonSchemaTestCase `json:"tests"` +} +type jsonSchemaTestCase struct { + Description string `json:"description"` + Data interface{} `json:"data"` + Valid bool `json:"valid"` +} + +func TestSuite(t *testing.T) { + + wd, err := os.Getwd() + if err != nil { + panic(err.Error()) + } + wd = filepath.Join(wd, "testdata") + + go func() { + err := http.ListenAndServe(":1234", http.FileServer(http.Dir(filepath.Join(wd, "remotes")))) + if err != nil { + + panic(err.Error()) + } + }() + + //Skip any directories not named appropiately + // filepath.Walk will also visit files in the root of the test directory + testDirectories := regexp.MustCompile(`^draft\d+$`) + + err = filepath.Walk(wd, func(path string, fileInfo os.FileInfo, err error) error { + if fileInfo.IsDir() && path != wd && !testDirectories.MatchString(fileInfo.Name()) { + return filepath.SkipDir + } + if !strings.HasSuffix(fileInfo.Name(), ".json") { + return nil + } + file, err := os.Open(path) + if err != nil { + t.Errorf("Error (%s)\n", err.Error()) + } + fmt.Println(file.Name()) + + var tests []jsonSchemaTest + d := json.NewDecoder(file) + d.UseNumber() + err = d.Decode(&tests) + + if err != nil { + t.Errorf("Error (%s)\n", err.Error()) + } + + for _, test := range tests { + fmt.Println(" " + test.Description) + + if test.Disabled { + continue + } + + testSchemaLoader := NewRawLoader(test.Schema) + testSchema, err := NewSchema(testSchemaLoader) + + if err != nil { + t.Errorf("Error (%s)\n", err.Error()) + } + + for _, testCase := range test.Tests { + testDataLoader := NewRawLoader(testCase.Data) + result, err := testSchema.Validate(testDataLoader) + + if err != nil { + t.Errorf("Error (%s)\n", err.Error()) + } + + if result.Valid() != testCase.Valid { + schemaString, _ := marshalToJsonString(test.Schema) + testCaseString, _ := marshalToJsonString(testCase.Data) + + t.Errorf("Test failed : %s\n"+ + "%s.\n"+ + "%s.\n"+ + "expects: %t, given %t\n"+ + "Schema: %s\n"+ + "Data: %s\n", + file.Name(), + test.Description, + testCase.Description, + testCase.Valid, + result.Valid(), + *schemaString, + *testCaseString) + } + } + } + return nil + }) + if err != nil { + t.Errorf("Error (%s)\n", err.Error()) + } +} diff --git a/vendor/github.com/xeipuuv/gojsonschema/locales.go b/vendor/github.com/xeipuuv/gojsonschema/locales.go index 9446f84..7bd9a9d 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/locales.go +++ b/vendor/github.com/xeipuuv/gojsonschema/locales.go @@ -36,16 +36,19 @@ type ( NumberNot() string MissingDependency() string Internal() string + Const() string Enum() string ArrayNotEnoughItems() string ArrayNoAdditionalItems() string ArrayMinItems() string ArrayMaxItems() string Unique() string + ArrayContains() string ArrayMinProperties() string ArrayMaxProperties() string AdditionalPropertyNotAllowed() string InvalidPropertyPattern() string + InvalidPropertyName() string StringGTE() string StringLTE() string DoesNotMatchPattern() string @@ -76,6 +79,9 @@ type ( HttpBadStatus() string ParseError() string + ConditionThen() string + ConditionElse() string + // ErrorFormat ErrorFormat() string } @@ -116,6 +122,10 @@ func (l DefaultLocale) Internal() string { return `Internal Error {{.error}}` } +func (l DefaultLocale) Const() string { + return `{{.field}} does not match: {{.allowed}}` +} + func (l DefaultLocale) Enum() string { return `{{.field}} must be one of the following: {{.allowed}}` } @@ -140,6 +150,10 @@ func (l DefaultLocale) Unique() string { return `{{.type}} items must be unique` } +func (l DefaultLocale) ArrayContains() string { + return `At least one of the items must match` +} + func (l DefaultLocale) ArrayMinProperties() string { return `Must have at least {{.min}} properties` } @@ -156,6 +170,10 @@ func (l DefaultLocale) InvalidPropertyPattern() string { return `Property "{{.property}}" does not match pattern {{.pattern}}` } +func (l DefaultLocale) InvalidPropertyName() string { + return `Property name of "{{.property}}" does not match` +} + func (l DefaultLocale) StringGTE() string { return `String length must be greater than or equal to {{.min}}` } @@ -271,6 +289,15 @@ func (l DefaultLocale) ParseError() string { return `Expected: {{.expected}}, given: Invalid JSON` } +//If/Else +func (l DefaultLocale) ConditionThen() string { + return `Must validate "then" as "if" was valid` +} + +func (l DefaultLocale) ConditionElse() string { + return `Must validate "else" as "if" was not valid` +} + const ( STRING_NUMBER = "number" STRING_ARRAY_OF_STRINGS = "array of strings" diff --git a/vendor/github.com/xeipuuv/gojsonschema/result.go b/vendor/github.com/xeipuuv/gojsonschema/result.go index 6ad56ae..7896f31 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/result.go +++ b/vendor/github.com/xeipuuv/gojsonschema/result.go @@ -40,10 +40,12 @@ type ( Field() string SetType(string) Type() string - SetContext(*jsonContext) - Context() *jsonContext + SetContext(*JsonContext) + Context() *JsonContext SetDescription(string) Description() string + SetDescriptionFormat(string) + DescriptionFormat() string SetValue(interface{}) Value() interface{} SetDetails(ErrorDetails) @@ -55,11 +57,12 @@ type ( // ResultErrorFields implements the ResultError interface, so custom errors // can be defined by just embedding this type ResultErrorFields struct { - errorType string // A string with the type of error (i.e. invalid_type) - context *jsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ... - description string // A human readable error message - value interface{} // Value given by the JSON file that is the source of the error - details ErrorDetails + errorType string // A string with the type of error (i.e. invalid_type) + context *JsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ... + description string // A human readable error message + descriptionFormat string // A format for human readable error message + value interface{} // Value given by the JSON file that is the source of the error + details ErrorDetails } Result struct { @@ -90,11 +93,11 @@ func (v *ResultErrorFields) Type() string { return v.errorType } -func (v *ResultErrorFields) SetContext(context *jsonContext) { +func (v *ResultErrorFields) SetContext(context *JsonContext) { v.context = context } -func (v *ResultErrorFields) Context() *jsonContext { +func (v *ResultErrorFields) Context() *JsonContext { return v.context } @@ -106,6 +109,14 @@ func (v *ResultErrorFields) Description() string { return v.description } +func (v *ResultErrorFields) SetDescriptionFormat(descriptionFormat string) { + v.descriptionFormat = descriptionFormat +} + +func (v *ResultErrorFields) DescriptionFormat() string { + return v.descriptionFormat +} + func (v *ResultErrorFields) SetValue(value interface{}) { v.value = value } @@ -155,7 +166,19 @@ func (v *Result) Errors() []ResultError { return v.errors } -func (v *Result) addError(err ResultError, context *jsonContext, value interface{}, details ErrorDetails) { +// Add a fully filled error to the error set +// SetDescription() will be called with the result of the parsed err.DescriptionFormat() +func (v *Result) AddError(err ResultError, details ErrorDetails) { + if _, exists := details["context"]; !exists && err.Context() != nil { + details["context"] = err.Context().String() + } + + err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details)) + + v.errors = append(v.errors, err) +} + +func (v *Result) addInternalError(err ResultError, context *JsonContext, value interface{}, details ErrorDetails) { newError(err, context, value, Locale, details) v.errors = append(v.errors, err) v.score -= 2 // results in a net -1 when added to the +1 we get at the end of the validation function diff --git a/vendor/github.com/xeipuuv/gojsonschema/schema.go b/vendor/github.com/xeipuuv/gojsonschema/schema.go index f1fbde3..0746a59 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/schema.go +++ b/vendor/github.com/xeipuuv/gojsonschema/schema.go @@ -28,6 +28,7 @@ package gojsonschema import ( "errors" + "math/big" "reflect" "regexp" "text/template" @@ -64,13 +65,6 @@ func NewSchema(l JSONLoader) (*Schema, error) { return nil, err } doc = spd.Document - - // Deal with fragment pointers - jsonPointer := ref.GetPointer() - doc, _, err = jsonPointer.Get(doc) - if err != nil { - return nil, err - } } else { // Load JSON directly doc, err = l.LoadJSON() @@ -78,7 +72,8 @@ func NewSchema(l JSONLoader) (*Schema, error) { return nil, err } } - d.pool.SetStandaloneDocument(doc) + + d.pool.ParseReferences(doc, ref) err = d.parse(doc) if err != nil { @@ -112,6 +107,16 @@ func (d *Schema) SetRootSchemaName(name string) { // func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) error { + // As of draft 6 "true" is equivalent to an empty schema "{}" and false equals "{"not":{}}" + if isKind(documentNode, reflect.Bool) { + b := documentNode.(bool) + if b { + documentNode = map[string]interface{}{} + } else { + documentNode = map[string]interface{}{"not": true} + } + } + if !isKind(documentNode, reflect.Map) { return errors.New(formatErrorDescription( Locale.ParseError(), @@ -120,28 +125,46 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) }, )) } + + m := documentNode.(map[string]interface{}) + if currentSchema.parent == nil { currentSchema.ref = &d.documentReference currentSchema.id = &d.documentReference + + if existsMapKey(m, KEY_SCHEMA) && false { + if !isKind(m[KEY_SCHEMA], reflect.String) { + return errors.New(formatErrorDescription( + Locale.InvalidType(), + ErrorDetails{ + "expected": TYPE_STRING, + "given": KEY_SCHEMA, + }, + )) + } + } } if currentSchema.id == nil && currentSchema.parent != nil { currentSchema.id = currentSchema.parent.id } - m := documentNode.(map[string]interface{}) - - // id - if existsMapKey(m, KEY_ID) && !isKind(m[KEY_ID], reflect.String) { + // In draft 6 the id keyword was renamed to $id + // Use the old id by default + keyID := KEY_ID_NEW + if existsMapKey(m, KEY_ID) { + keyID = KEY_ID + } + if existsMapKey(m, keyID) && !isKind(m[keyID], reflect.String) { return errors.New(formatErrorDescription( Locale.InvalidType(), ErrorDetails{ "expected": TYPE_STRING, - "given": KEY_ID, + "given": keyID, }, )) } - if k, ok := m[KEY_ID].(string); ok { + if k, ok := m[keyID].(string); ok { jsonReference, err := gojsonreference.NewJsonReference(k) if err != nil { return err @@ -157,90 +180,15 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } } - // Add schema to document cache. The same id is passed down to subsequent - // subschemas, but as only the first and top one is used it will always reference - // the correct schema. Doing it once here prevents having - // to do this same step at every corner case. - d.referencePool.Add(currentSchema.id.String(), currentSchema) - - // $subSchema - if existsMapKey(m, KEY_SCHEMA) { - if !isKind(m[KEY_SCHEMA], reflect.String) { - return errors.New(formatErrorDescription( - Locale.InvalidType(), - ErrorDetails{ - "expected": TYPE_STRING, - "given": KEY_SCHEMA, - }, - )) - } - schemaRef := m[KEY_SCHEMA].(string) - schemaReference, err := gojsonreference.NewJsonReference(schemaRef) - currentSchema.subSchema = &schemaReference - if err != nil { - return err - } - } - - // $ref - if existsMapKey(m, KEY_REF) && !isKind(m[KEY_REF], reflect.String) { - return errors.New(formatErrorDescription( - Locale.InvalidType(), - ErrorDetails{ - "expected": TYPE_STRING, - "given": KEY_REF, - }, - )) - } - if k, ok := m[KEY_REF].(string); ok { - - jsonReference, err := gojsonreference.NewJsonReference(k) - if err != nil { - return err - } - - if jsonReference.HasFullUrl { - currentSchema.ref = &jsonReference - } else { - inheritedReference, err := currentSchema.id.Inherits(jsonReference) - if err != nil { - return err - } - currentSchema.ref = inheritedReference - } - if sch, ok := d.referencePool.Get(currentSchema.ref.String()); ok { - currentSchema.refSchema = sch - } else { - err := d.parseReference(documentNode, currentSchema) - - if err != nil { - return err - } - - return nil - } - } - // definitions if existsMapKey(m, KEY_DEFINITIONS) { - if isKind(m[KEY_DEFINITIONS], reflect.Map) { - currentSchema.definitions = make(map[string]*subSchema) - for dk, dv := range m[KEY_DEFINITIONS].(map[string]interface{}) { - if isKind(dv, reflect.Map) { + if isKind(m[KEY_DEFINITIONS], reflect.Map, reflect.Bool) { + for _, dv := range m[KEY_DEFINITIONS].(map[string]interface{}) { + if isKind(dv, reflect.Map, reflect.Bool) { - ref, err := gojsonreference.NewJsonReference("#/" + KEY_DEFINITIONS + "/" + dk) - if err != nil { - return err - } + newSchema := &subSchema{property: KEY_DEFINITIONS, parent: currentSchema} - newSchemaID, err := currentSchema.id.Inherits(ref) - if err != nil { - return err - } - newSchema := &subSchema{property: KEY_DEFINITIONS, parent: currentSchema, id: newSchemaID} - currentSchema.definitions[dk] = newSchema - - err = d.parseSchema(dv, newSchema) + err := d.parseSchema(dv, newSchema) if err != nil { return err @@ -295,6 +243,39 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) currentSchema.description = &k } + // $ref + if existsMapKey(m, KEY_REF) && !isKind(m[KEY_REF], reflect.String) { + return errors.New(formatErrorDescription( + Locale.InvalidType(), + ErrorDetails{ + "expected": TYPE_STRING, + "given": KEY_REF, + }, + )) + } + + if k, ok := m[KEY_REF].(string); ok { + + jsonReference, err := gojsonreference.NewJsonReference(k) + if err != nil { + return err + } + + currentSchema.ref = &jsonReference + + if sch, ok := d.referencePool.Get(currentSchema.ref.String()); ok { + currentSchema.refSchema = sch + } else { + err := d.parseReference(documentNode, currentSchema) + + if err != nil { + return err + } + + return nil + } + } + // type if existsMapKey(m, KEY_TYPE) { if isKind(m[KEY_TYPE], reflect.String) { @@ -396,6 +377,26 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } } + // propertyNames + if existsMapKey(m, KEY_PROPERTY_NAMES) { + if isKind(m[KEY_PROPERTY_NAMES], reflect.Map, reflect.Bool) { + newSchema := &subSchema{property: KEY_PROPERTY_NAMES, parent: currentSchema, ref: currentSchema.ref} + currentSchema.propertyNames = newSchema + err := d.parseSchema(m[KEY_PROPERTY_NAMES], newSchema) + if err != nil { + return err + } + } else { + return errors.New(formatErrorDescription( + Locale.InvalidType(), + ErrorDetails{ + "expected": STRING_SCHEMA, + "given": KEY_PATTERN_PROPERTIES, + }, + )) + } + } + // dependencies if existsMapKey(m, KEY_DEPENDENCIES) { err := d.parseDependencies(m[KEY_DEPENDENCIES], currentSchema) @@ -408,7 +409,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) if existsMapKey(m, KEY_ITEMS) { if isKind(m[KEY_ITEMS], reflect.Slice) { for _, itemElement := range m[KEY_ITEMS].([]interface{}) { - if isKind(itemElement, reflect.Map) { + if isKind(itemElement, reflect.Map, reflect.Bool) { newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS} newSchema.ref = currentSchema.ref currentSchema.AddItemsChild(newSchema) @@ -427,7 +428,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } currentSchema.itemsChildrenIsSingleSchema = false } - } else if isKind(m[KEY_ITEMS], reflect.Map) { + } else if isKind(m[KEY_ITEMS], reflect.Map, reflect.Bool) { newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS} newSchema.ref = currentSchema.ref currentSchema.AddItemsChild(newSchema) @@ -482,7 +483,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) }, )) } - if *multipleOfValue <= 0 { + if multipleOfValue.Cmp(big.NewFloat(0)) <= 0 { return errors.New(formatErrorDescription( Locale.GreaterThanZero(), ErrorDetails{"number": KEY_MULTIPLE_OF}, @@ -512,10 +513,15 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } exclusiveMinimumValue := m[KEY_EXCLUSIVE_MINIMUM].(bool) currentSchema.exclusiveMinimum = exclusiveMinimumValue + } else if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) { + minimumValue := mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM]) + + currentSchema.minimum = minimumValue + currentSchema.exclusiveMinimum = true } else { return errors.New(formatErrorDescription( - Locale.MustBeOfA(), - ErrorDetails{"x": KEY_EXCLUSIVE_MINIMUM, "y": TYPE_BOOLEAN}, + Locale.InvalidType(), + ErrorDetails{"expected": TYPE_BOOLEAN + ", " + TYPE_NUMBER, "given": KEY_EXCLUSIVE_MINIMUM}, )) } } @@ -541,16 +547,21 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } exclusiveMaximumValue := m[KEY_EXCLUSIVE_MAXIMUM].(bool) currentSchema.exclusiveMaximum = exclusiveMaximumValue + } else if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) { + maximumValue := mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM]) + + currentSchema.maximum = maximumValue + currentSchema.exclusiveMaximum = true } else { return errors.New(formatErrorDescription( - Locale.MustBeOfA(), - ErrorDetails{"x": KEY_EXCLUSIVE_MAXIMUM, "y": STRING_NUMBER}, + Locale.InvalidType(), + ErrorDetails{"expected": TYPE_BOOLEAN + ", " + TYPE_NUMBER, "given": KEY_EXCLUSIVE_MAXIMUM}, )) } } if currentSchema.minimum != nil && currentSchema.maximum != nil { - if *currentSchema.minimum > *currentSchema.maximum { + if currentSchema.minimum.Cmp(currentSchema.maximum) == 1 { return errors.New(formatErrorDescription( Locale.CannotBeGT(), ErrorDetails{"x": KEY_MINIMUM, "y": KEY_MAXIMUM}, @@ -744,8 +755,24 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } } + if existsMapKey(m, KEY_CONTAINS) { + newSchema := &subSchema{property: KEY_CONTAINS, parent: currentSchema, ref: currentSchema.ref} + currentSchema.contains = newSchema + err := d.parseSchema(m[KEY_CONTAINS], newSchema) + if err != nil { + return err + } + } + // validation : all + if existsMapKey(m, KEY_CONST) { + err := currentSchema.AddConst(m[KEY_CONST]) + if err != nil { + return err + } + } + if existsMapKey(m, KEY_ENUM) { if isKind(m[KEY_ENUM], reflect.Slice) { for _, v := range m[KEY_ENUM].([]interface{}) { @@ -819,7 +846,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } if existsMapKey(m, KEY_NOT) { - if isKind(m[KEY_NOT], reflect.Map) { + if isKind(m[KEY_NOT], reflect.Map, reflect.Bool) { newSchema := &subSchema{property: KEY_NOT, parent: currentSchema, ref: currentSchema.ref} currentSchema.SetNot(newSchema) err := d.parseSchema(m[KEY_NOT], newSchema) @@ -834,6 +861,54 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) } } + if existsMapKey(m, KEY_IF) { + if isKind(m[KEY_IF], reflect.Map, reflect.Bool) { + newSchema := &subSchema{property: KEY_IF, parent: currentSchema, ref: currentSchema.ref} + currentSchema.SetIf(newSchema) + err := d.parseSchema(m[KEY_IF], newSchema) + if err != nil { + return err + } + } else { + return errors.New(formatErrorDescription( + Locale.MustBeOfAn(), + ErrorDetails{"x": KEY_IF, "y": TYPE_OBJECT}, + )) + } + } + + if existsMapKey(m, KEY_THEN) { + if isKind(m[KEY_THEN], reflect.Map, reflect.Bool) { + newSchema := &subSchema{property: KEY_THEN, parent: currentSchema, ref: currentSchema.ref} + currentSchema.SetThen(newSchema) + err := d.parseSchema(m[KEY_THEN], newSchema) + if err != nil { + return err + } + } else { + return errors.New(formatErrorDescription( + Locale.MustBeOfAn(), + ErrorDetails{"x": KEY_THEN, "y": TYPE_OBJECT}, + )) + } + } + + if existsMapKey(m, KEY_ELSE) { + if isKind(m[KEY_ELSE], reflect.Map, reflect.Bool) { + newSchema := &subSchema{property: KEY_ELSE, parent: currentSchema, ref: currentSchema.ref} + currentSchema.SetElse(newSchema) + err := d.parseSchema(m[KEY_ELSE], newSchema) + if err != nil { + return err + } + } else { + return errors.New(formatErrorDescription( + Locale.MustBeOfAn(), + ErrorDetails{"x": KEY_ELSE, "y": TYPE_OBJECT}, + )) + } + } + return nil } @@ -843,43 +918,31 @@ func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSche dsp *schemaPoolDocument err error ) - jsonPointer := currentSchema.ref.GetPointer() - standaloneDocument := d.pool.GetStandaloneDocument() newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref} - if currentSchema.ref.HasFragmentOnly { - refdDocumentNode, _, err = jsonPointer.Get(standaloneDocument) - if err != nil { - return err - } + d.referencePool.Add(currentSchema.ref.String(), newSchema) - } else { - dsp, err = d.pool.GetDocument(*currentSchema.ref) - if err != nil { - return err - } - newSchema.id = currentSchema.ref + dsp, err = d.pool.GetDocument(*currentSchema.ref) + if err != nil { + return err + } + newSchema.id = currentSchema.ref - refdDocumentNode, _, err = jsonPointer.Get(dsp.Document) - - if err != nil { - return err - } + refdDocumentNode = dsp.Document + if err != nil { + return err } - if !isKind(refdDocumentNode, reflect.Map) { + if !isKind(refdDocumentNode, reflect.Map, reflect.Bool) { return errors.New(formatErrorDescription( Locale.MustBeOfType(), ErrorDetails{"key": STRING_SCHEMA, "type": TYPE_OBJECT}, )) } - // returns the loaded referenced subSchema for the caller to update its current subSchema - newSchemaDocument := refdDocumentNode.(map[string]interface{}) - - err = d.parseSchema(newSchemaDocument, newSchema) + err = d.parseSchema(refdDocumentNode, newSchema) if err != nil { return err } @@ -947,7 +1010,7 @@ func (d *Schema) parseDependencies(documentNode interface{}, currentSchema *subS currentSchema.dependencies[k] = valuesToRegister } - case reflect.Map: + case reflect.Map, reflect.Bool: depSchema := &subSchema{property: k, parent: currentSchema, ref: currentSchema.ref} err := d.parseSchema(m[k], depSchema) if err != nil { diff --git a/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go b/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go index ff9715f..65c91e4 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go +++ b/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go @@ -28,6 +28,7 @@ package gojsonschema import ( "errors" + "reflect" "github.com/xeipuuv/gojsonreference" ) @@ -38,7 +39,6 @@ type schemaPoolDocument struct { type schemaPool struct { schemaPoolDocuments map[string]*schemaPoolDocument - standaloneDocument interface{} jsonLoaderFactory JSONLoaderFactory } @@ -46,18 +46,74 @@ func newSchemaPool(f JSONLoaderFactory) *schemaPool { p := &schemaPool{} p.schemaPoolDocuments = make(map[string]*schemaPoolDocument) - p.standaloneDocument = nil p.jsonLoaderFactory = f return p } -func (p *schemaPool) SetStandaloneDocument(document interface{}) { - p.standaloneDocument = document +func (p *schemaPool) ParseReferences(document interface{}, ref gojsonreference.JsonReference) { + // Only the root document should be added to the schema pool + p.schemaPoolDocuments[ref.String()] = &schemaPoolDocument{Document: document} + p.parseReferencesRecursive(document, ref) } -func (p *schemaPool) GetStandaloneDocument() (document interface{}) { - return p.standaloneDocument +func (p *schemaPool) parseReferencesRecursive(document interface{}, ref gojsonreference.JsonReference) { + // parseReferencesRecursive parses a JSON document and resolves all $id and $ref references. + // For $ref references it takes into account the $id scope it is in and replaces + // the reference by the absolute resolved reference + + // When encountering errors it fails silently. Error handling is done when the schema + // is syntactically parsed and any error encountered here should also come up there. + switch m := document.(type) { + case []interface{}: + for _, v := range m { + p.parseReferencesRecursive(v, ref) + } + case map[string]interface{}: + localRef := &ref + + keyID := KEY_ID_NEW + if existsMapKey(m, KEY_ID) { + keyID = KEY_ID + } + if existsMapKey(m, keyID) && isKind(m[keyID], reflect.String) { + jsonReference, err := gojsonreference.NewJsonReference(m[keyID].(string)) + if err == nil { + localRef, err = ref.Inherits(jsonReference) + if err == nil { + p.schemaPoolDocuments[localRef.String()] = &schemaPoolDocument{Document: document} + } + } + } + + if existsMapKey(m, KEY_REF) && isKind(m[KEY_REF], reflect.String) { + jsonReference, err := gojsonreference.NewJsonReference(m[KEY_REF].(string)) + if err == nil { + absoluteRef, err := localRef.Inherits(jsonReference) + if err == nil { + m[KEY_REF] = absoluteRef.String() + } + } + } + + for k, v := range m { + // const and enums should be interpreted literally, so ignore them + if k == KEY_CONST || k == KEY_ENUM { + continue + } + // Something like a property or a dependency is not a valid schema, as it might describe properties named "$ref", "$id" or "const", etc + // Therefore don't treat it like a schema. + if k == KEY_PROPERTIES || k == KEY_DEPENDENCIES || k == KEY_PATTERN_PROPERTIES { + if child, ok := v.(map[string]interface{}); ok { + for _, v := range child { + p.parseReferencesRecursive(v, *localRef) + } + } + } else { + p.parseReferencesRecursive(v, *localRef) + } + } + } } func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) { @@ -72,15 +128,11 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche internalLog("Get Document ( %s )", reference.String()) } - // It is not possible to load anything that is not canonical... - if !reference.IsCanonical() { - return nil, errors.New(formatErrorDescription( - Locale.ReferenceMustBeCanonical(), - ErrorDetails{"reference": reference}, - )) - } - refToUrl := reference - refToUrl.GetUrl().Fragment = "" + // Create a deep copy, so we can remove the fragment part later on without altering the original + refToUrl, _ := gojsonreference.NewJsonReference(reference.String()) + + // First check if the given fragment is a location independent identifier + // http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3 if spd, ok = p.schemaPoolDocuments[refToUrl.String()]; ok { if internalLogEnabled { @@ -89,15 +141,52 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche return spd, nil } + // If the given reference is not a location independent identifier, + // strip the fragment and look for a document with it's base URI + + refToUrl.GetUrl().Fragment = "" + + if cachedSpd, ok := p.schemaPoolDocuments[refToUrl.String()]; ok { + document, _, err := reference.GetPointer().Get(cachedSpd.Document) + + if err != nil { + return nil, err + } + + if internalLogEnabled { + internalLog(" From pool") + } + + spd = &schemaPoolDocument{Document: document} + p.schemaPoolDocuments[reference.String()] = spd + + return spd, nil + } + + // It is not possible to load anything remotely that is not canonical... + if !reference.IsCanonical() { + return nil, errors.New(formatErrorDescription( + Locale.ReferenceMustBeCanonical(), + ErrorDetails{"reference": reference.String()}, + )) + } + jsonReferenceLoader := p.jsonLoaderFactory.New(reference.String()) document, err := jsonReferenceLoader.LoadJSON() + if err != nil { return nil, err } - spd = &schemaPoolDocument{Document: document} - // add the document to the pool for potential later use - p.schemaPoolDocuments[refToUrl.String()] = spd + // add the whole document to the pool for potential re-use + p.ParseReferences(document, refToUrl) - return spd, nil + // resolve the potential fragment and also cache it + document, _, err = reference.GetPointer().Get(document) + + if err != nil { + return nil, err + } + + return &schemaPoolDocument{Document: document}, nil } diff --git a/vendor/github.com/xeipuuv/gojsonschema/schema_test.go b/vendor/github.com/xeipuuv/gojsonschema/schema_test.go index 9c40e71..d35415e 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/schema_test.go +++ b/vendor/github.com/xeipuuv/gojsonschema/schema_test.go @@ -30,13 +30,8 @@ import ( "fmt" "io" "io/ioutil" - "net/http" "os" - "reflect" - "regexp" - "sort" - "strconv" - "strings" + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -44,407 +39,6 @@ import ( const displayErrorMessages = false -var rxInvoice = regexp.MustCompile("^[A-Z]{2}-[0-9]{5}") -var rxSplitErrors = regexp.MustCompile(", ?") - -// Used for remote schema in ref/schema_5.json that defines "uri" and "regex" types -type alwaysTrueFormatChecker struct{} -type invoiceFormatChecker struct{} -type evenNumberFormatChecker struct{} - -func (a alwaysTrueFormatChecker) IsFormat(input interface{}) bool { - return true -} - -func (a evenNumberFormatChecker) IsFormat(input interface{}) bool { - - asFloat64, ok := input.(float64) - if ok == false { - return false - } - - return int(asFloat64)%2 == 0 -} - -func (a invoiceFormatChecker) IsFormat(input interface{}) bool { - - asString, ok := input.(string) - if ok == false { - return false - } - - return rxInvoice.MatchString(asString) -} - -func TestJsonSchemaTestSuite(t *testing.T) { - - JsonSchemaTestSuiteMap := []map[string]string{ - - {"phase": "integer type matches integers", "test": "an integer is an integer", "schema": "type/schema_0.json", "data": "type/data_00.json", "valid": "true"}, - {"phase": "integer type matches integers", "test": "a float is not an integer", "schema": "type/schema_0.json", "data": "type/data_01.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "integer type matches integers", "test": "a string is not an integer", "schema": "type/schema_0.json", "data": "type/data_02.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "integer type matches integers", "test": "an object is not an integer", "schema": "type/schema_0.json", "data": "type/data_03.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "integer type matches integers", "test": "an array is not an integer", "schema": "type/schema_0.json", "data": "type/data_04.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "integer type matches integers", "test": "a boolean is not an integer", "schema": "type/schema_0.json", "data": "type/data_05.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "integer type matches integers", "test": "null is not an integer", "schema": "type/schema_0.json", "data": "type/data_06.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "number type matches numbers", "test": "an integer is a number", "schema": "type/schema_1.json", "data": "type/data_10.json", "valid": "true"}, - {"phase": "number type matches numbers", "test": "a float is a number", "schema": "type/schema_1.json", "data": "type/data_11.json", "valid": "true"}, - {"phase": "number type matches numbers", "test": "a string is not a number", "schema": "type/schema_1.json", "data": "type/data_12.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "number type matches numbers", "test": "an object is not a number", "schema": "type/schema_1.json", "data": "type/data_13.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "number type matches numbers", "test": "an array is not a number", "schema": "type/schema_1.json", "data": "type/data_14.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "number type matches numbers", "test": "a boolean is not a number", "schema": "type/schema_1.json", "data": "type/data_15.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "number type matches numbers", "test": "null is not a number", "schema": "type/schema_1.json", "data": "type/data_16.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "1 is not a string", "schema": "type/schema_2.json", "data": "type/data_20.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "a float is not a string", "schema": "type/schema_2.json", "data": "type/data_21.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "a string is a string", "schema": "type/schema_2.json", "data": "type/data_22.json", "valid": "true"}, - {"phase": "string type matches strings", "test": "an object is not a string", "schema": "type/schema_2.json", "data": "type/data_23.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "an array is not a string", "schema": "type/schema_2.json", "data": "type/data_24.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "a boolean is not a string", "schema": "type/schema_2.json", "data": "type/data_25.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "string type matches strings", "test": "null is not a string", "schema": "type/schema_2.json", "data": "type/data_26.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "an integer is not an object", "schema": "type/schema_3.json", "data": "type/data_30.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "a float is not an object", "schema": "type/schema_3.json", "data": "type/data_31.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "a string is not an object", "schema": "type/schema_3.json", "data": "type/data_32.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "an object is an object", "schema": "type/schema_3.json", "data": "type/data_33.json", "valid": "true"}, - {"phase": "object type matches objects", "test": "an array is not an object", "schema": "type/schema_3.json", "data": "type/data_34.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "a boolean is not an object", "schema": "type/schema_3.json", "data": "type/data_35.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object type matches objects", "test": "null is not an object", "schema": "type/schema_3.json", "data": "type/data_36.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "an integer is not an array", "schema": "type/schema_4.json", "data": "type/data_40.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "a float is not an array", "schema": "type/schema_4.json", "data": "type/data_41.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "a string is not an array", "schema": "type/schema_4.json", "data": "type/data_42.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "an object is not an array", "schema": "type/schema_4.json", "data": "type/data_43.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "an array is not an array", "schema": "type/schema_4.json", "data": "type/data_44.json", "valid": "true"}, - {"phase": "array type matches arrays", "test": "a boolean is not an array", "schema": "type/schema_4.json", "data": "type/data_45.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "array type matches arrays", "test": "null is not an array", "schema": "type/schema_4.json", "data": "type/data_46.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "an integer is not a boolean", "schema": "type/schema_5.json", "data": "type/data_50.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "a float is not a boolean", "schema": "type/schema_5.json", "data": "type/data_51.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "a string is not a boolean", "schema": "type/schema_5.json", "data": "type/data_52.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "an object is not a boolean", "schema": "type/schema_5.json", "data": "type/data_53.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "an array is not a boolean", "schema": "type/schema_5.json", "data": "type/data_54.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "a boolean is not a boolean", "schema": "type/schema_5.json", "data": "type/data_55.json", "valid": "true", "errors": "invalid_type"}, - {"phase": "boolean type matches booleans", "test": "null is not a boolean", "schema": "type/schema_5.json", "data": "type/data_56.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "an integer is not null", "schema": "type/schema_6.json", "data": "type/data_60.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "a float is not null", "schema": "type/schema_6.json", "data": "type/data_61.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "a string is not null", "schema": "type/schema_6.json", "data": "type/data_62.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "an object is not null", "schema": "type/schema_6.json", "data": "type/data_63.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "an array is not null", "schema": "type/schema_6.json", "data": "type/data_64.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "a boolean is not null", "schema": "type/schema_6.json", "data": "type/data_65.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "null type matches only the null object", "test": "null is null", "schema": "type/schema_6.json", "data": "type/data_66.json", "valid": "true"}, - {"phase": "multiple types can be specified in an array", "test": "an integer is valid", "schema": "type/schema_7.json", "data": "type/data_70.json", "valid": "true"}, - {"phase": "multiple types can be specified in an array", "test": "a string is valid", "schema": "type/schema_7.json", "data": "type/data_71.json", "valid": "true"}, - {"phase": "multiple types can be specified in an array", "test": "a float is invalid", "schema": "type/schema_7.json", "data": "type/data_72.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "multiple types can be specified in an array", "test": "an object is invalid", "schema": "type/schema_7.json", "data": "type/data_73.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "multiple types can be specified in an array", "test": "an array is invalid", "schema": "type/schema_7.json", "data": "type/data_74.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "multiple types can be specified in an array", "test": "a boolean is invalid", "schema": "type/schema_7.json", "data": "type/data_75.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "multiple types can be specified in an array", "test": "null is invalid", "schema": "type/schema_7.json", "data": "type/data_76.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "required validation", "test": "present required property is valid", "schema": "required/schema_0.json", "data": "required/data_00.json", "valid": "true"}, - {"phase": "required validation", "test": "non-present required property is invalid", "schema": "required/schema_0.json", "data": "required/data_01.json", "valid": "false", "errors": "required"}, - {"phase": "required default validation", "test": "not required by default", "schema": "required/schema_1.json", "data": "required/data_10.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "unique array of integers is valid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_00.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "non-unique array of integers is invalid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_01.json", "valid": "false", "errors": "unique"}, - {"phase": "uniqueItems validation", "test": "numbers are unique if mathematically unequal", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_02.json", "valid": "false", "errors": "unique, unique"}, - {"phase": "uniqueItems validation", "test": "unique array of objects is valid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_03.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "non-unique array of objects is invalid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_04.json", "valid": "false", "errors": "unique"}, - {"phase": "uniqueItems validation", "test": "unique array of nested objects is valid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_05.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "non-unique array of nested objects is invalid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_06.json", "valid": "false", "errors": "unique"}, - {"phase": "uniqueItems validation", "test": "unique array of arrays is valid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_07.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "non-unique array of arrays is invalid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_08.json", "valid": "false", "errors": "unique"}, - {"phase": "uniqueItems validation", "test": "1 and true are unique", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_09.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "0 and false are unique", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_010.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "unique heterogeneous types are valid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_011.json", "valid": "true"}, - {"phase": "uniqueItems validation", "test": "non-unique heterogeneous types are invalid", "schema": "uniqueItems/schema_0.json", "data": "uniqueItems/data_012.json", "valid": "false", "errors": "unique"}, - {"phase": "pattern validation", "test": "a matching pattern is valid", "schema": "pattern/schema_0.json", "data": "pattern/data_00.json", "valid": "true"}, - {"phase": "pattern validation", "test": "a non-matching pattern is invalid", "schema": "pattern/schema_0.json", "data": "pattern/data_01.json", "valid": "false", "errors": "pattern"}, - {"phase": "pattern validation", "test": "ignores non-strings", "schema": "pattern/schema_0.json", "data": "pattern/data_02.json", "valid": "true"}, - {"phase": "simple enum validation", "test": "one of the enum is valid", "schema": "enum/schema_0.json", "data": "enum/data_00.json", "valid": "true"}, - {"phase": "simple enum validation", "test": "something else is invalid", "schema": "enum/schema_0.json", "data": "enum/data_01.json", "valid": "false", "errors": "enum"}, - {"phase": "heterogeneous enum validation", "test": "one of the enum is valid", "schema": "enum/schema_1.json", "data": "enum/data_10.json", "valid": "true"}, - {"phase": "heterogeneous enum validation", "test": "something else is invalid", "schema": "enum/schema_1.json", "data": "enum/data_11.json", "valid": "false", "errors": "enum"}, - {"phase": "heterogeneous enum validation", "test": "objects are deep compared", "schema": "enum/schema_1.json", "data": "enum/data_12.json", "valid": "false", "errors": "enum"}, - {"phase": "minLength validation", "test": "longer is valid", "schema": "minLength/schema_0.json", "data": "minLength/data_00.json", "valid": "true"}, - {"phase": "minLength validation", "test": "exact length is valid", "schema": "minLength/schema_0.json", "data": "minLength/data_01.json", "valid": "true"}, - {"phase": "minLength validation", "test": "too short is invalid", "schema": "minLength/schema_0.json", "data": "minLength/data_02.json", "valid": "false", "errors": "string_gte"}, - {"phase": "minLength validation", "test": "ignores non-strings", "schema": "minLength/schema_0.json", "data": "minLength/data_03.json", "valid": "true"}, - {"phase": "minLength validation", "test": "counts utf8 length correctly", "schema": "minLength/schema_0.json", "data": "minLength/data_04.json", "valid": "false", "errors": "string_gte"}, - {"phase": "maxLength validation", "test": "shorter is valid", "schema": "maxLength/schema_0.json", "data": "maxLength/data_00.json", "valid": "true"}, - {"phase": "maxLength validation", "test": "exact length is valid", "schema": "maxLength/schema_0.json", "data": "maxLength/data_01.json", "valid": "true"}, - {"phase": "maxLength validation", "test": "too long is invalid", "schema": "maxLength/schema_0.json", "data": "maxLength/data_02.json", "valid": "false", "errors": "string_lte"}, - {"phase": "maxLength validation", "test": "ignores non-strings", "schema": "maxLength/schema_0.json", "data": "maxLength/data_03.json", "valid": "true"}, - {"phase": "maxLength validation", "test": "counts utf8 length correctly", "schema": "maxLength/schema_0.json", "data": "maxLength/data_04.json", "valid": "true"}, - {"phase": "minimum validation", "test": "above the minimum is valid", "schema": "minimum/schema_0.json", "data": "minimum/data_00.json", "valid": "true"}, - {"phase": "minimum validation", "test": "below the minimum is invalid", "schema": "minimum/schema_0.json", "data": "minimum/data_01.json", "valid": "false", "errors": "number_gte"}, - {"phase": "minimum validation", "test": "ignores non-numbers", "schema": "minimum/schema_0.json", "data": "minimum/data_02.json", "valid": "true"}, - {"phase": "exclusiveMinimum validation", "test": "above the minimum is still valid", "schema": "minimum/schema_1.json", "data": "minimum/data_10.json", "valid": "true"}, - {"phase": "exclusiveMinimum validation", "test": "boundary point is invalid", "schema": "minimum/schema_1.json", "data": "minimum/data_11.json", "valid": "false", "errors": "number_gt"}, - {"phase": "maximum validation", "test": "below the maximum is valid", "schema": "maximum/schema_0.json", "data": "maximum/data_00.json", "valid": "true"}, - {"phase": "maximum validation", "test": "above the maximum is invalid", "schema": "maximum/schema_0.json", "data": "maximum/data_01.json", "valid": "false", "errors": "number_lte"}, - {"phase": "maximum validation", "test": "ignores non-numbers", "schema": "maximum/schema_0.json", "data": "maximum/data_02.json", "valid": "true"}, - {"phase": "exclusiveMaximum validation", "test": "below the maximum is still valid", "schema": "maximum/schema_1.json", "data": "maximum/data_10.json", "valid": "true"}, - {"phase": "exclusiveMaximum validation", "test": "boundary point is invalid", "schema": "maximum/schema_1.json", "data": "maximum/data_11.json", "valid": "false", "errors": "number_lt"}, - {"phase": "allOf", "test": "allOf", "schema": "allOf/schema_0.json", "data": "allOf/data_00.json", "valid": "true"}, - {"phase": "allOf", "test": "mismatch second", "schema": "allOf/schema_0.json", "data": "allOf/data_01.json", "valid": "false", "errors": "number_all_of, required"}, - {"phase": "allOf", "test": "mismatch first", "schema": "allOf/schema_0.json", "data": "allOf/data_02.json", "valid": "false", "errors": "number_all_of, required"}, - {"phase": "allOf", "test": "wrong type", "schema": "allOf/schema_0.json", "data": "allOf/data_03.json", "valid": "false", "errors": "number_all_of, invalid_type"}, - {"phase": "allOf with base schema", "test": "valid", "schema": "allOf/schema_1.json", "data": "allOf/data_10.json", "valid": "true"}, - {"phase": "allOf with base schema", "test": "mismatch base schema", "schema": "allOf/schema_1.json", "data": "allOf/data_11.json", "valid": "false", "errors": "required"}, - {"phase": "allOf with base schema", "test": "mismatch first allOf", "schema": "allOf/schema_1.json", "data": "allOf/data_12.json", "valid": "false", "errors": "number_all_of, required"}, - {"phase": "allOf with base schema", "test": "mismatch second allOf", "schema": "allOf/schema_1.json", "data": "allOf/data_13.json", "valid": "false", "errors": "number_all_of, required"}, - {"phase": "allOf with base schema", "test": "mismatch both", "schema": "allOf/schema_1.json", "data": "allOf/data_14.json", "valid": "false", "errors": "number_all_of, required, required"}, - {"phase": "allOf simple types", "test": "valid", "schema": "allOf/schema_2.json", "data": "allOf/data_20.json", "valid": "true"}, - {"phase": "allOf simple types", "test": "mismatch one", "schema": "allOf/schema_2.json", "data": "allOf/data_21.json", "valid": "false", "errors": "number_all_of, number_lte"}, - {"phase": "oneOf", "test": "first oneOf valid", "schema": "oneOf/schema_0.json", "data": "oneOf/data_00.json", "valid": "true"}, - {"phase": "oneOf", "test": "second oneOf valid", "schema": "oneOf/schema_0.json", "data": "oneOf/data_01.json", "valid": "true"}, - {"phase": "oneOf", "test": "both oneOf valid", "schema": "oneOf/schema_0.json", "data": "oneOf/data_02.json", "valid": "false", "errors": "number_one_of"}, - {"phase": "oneOf", "test": "neither oneOf valid", "schema": "oneOf/schema_0.json", "data": "oneOf/data_03.json", "valid": "false"}, - {"phase": "oneOf with base schema", "test": "mismatch base schema", "schema": "oneOf/schema_1.json", "data": "oneOf/data_10.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "oneOf with base schema", "test": "one oneOf valid", "schema": "oneOf/schema_1.json", "data": "oneOf/data_11.json", "valid": "true"}, - {"phase": "oneOf with base schema", "test": "both oneOf valid", "schema": "oneOf/schema_1.json", "data": "oneOf/data_12.json", "valid": "false", "errors": "number_one_of"}, - {"phase": "anyOf", "test": "first anyOf valid", "schema": "anyOf/schema_0.json", "data": "anyOf/data_00.json", "valid": "true"}, - {"phase": "anyOf", "test": "second anyOf valid", "schema": "anyOf/schema_0.json", "data": "anyOf/data_01.json", "valid": "true"}, - {"phase": "anyOf", "test": "both anyOf valid", "schema": "anyOf/schema_0.json", "data": "anyOf/data_02.json", "valid": "true"}, - {"phase": "anyOf", "test": "neither anyOf valid", "schema": "anyOf/schema_0.json", "data": "anyOf/data_03.json", "valid": "false", "errors": "number_any_of, number_gte"}, - {"phase": "anyOf with base schema", "test": "mismatch base schema", "schema": "anyOf/schema_1.json", "data": "anyOf/data_10.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "anyOf with base schema", "test": "one anyOf valid", "schema": "anyOf/schema_1.json", "data": "anyOf/data_11.json", "valid": "true"}, - {"phase": "anyOf with base schema", "test": "both anyOf invalid", "schema": "anyOf/schema_1.json", "data": "anyOf/data_12.json", "valid": "false", "errors": "number_any_of, string_lte"}, - {"phase": "not", "test": "allowed", "schema": "not/schema_0.json", "data": "not/data_00.json", "valid": "true"}, - {"phase": "not", "test": "disallowed", "schema": "not/schema_0.json", "data": "not/data_01.json", "valid": "false", "errors": "number_not"}, - {"phase": "not multiple types", "test": "valid", "schema": "not/schema_1.json", "data": "not/data_10.json", "valid": "true"}, - {"phase": "not multiple types", "test": "mismatch", "schema": "not/schema_1.json", "data": "not/data_11.json", "valid": "false", "errors": "number_not"}, - {"phase": "not multiple types", "test": "other mismatch", "schema": "not/schema_1.json", "data": "not/data_12.json", "valid": "false", "errors": "number_not"}, - {"phase": "not more complex schema", "test": "match", "schema": "not/schema_2.json", "data": "not/data_20.json", "valid": "true"}, - {"phase": "not more complex schema", "test": "other match", "schema": "not/schema_2.json", "data": "not/data_21.json", "valid": "true"}, - {"phase": "not more complex schema", "test": "mismatch", "schema": "not/schema_2.json", "data": "not/data_22.json", "valid": "false", "errors": "number_not"}, - {"phase": "minProperties validation", "test": "longer is valid", "schema": "minProperties/schema_0.json", "data": "minProperties/data_00.json", "valid": "true"}, - {"phase": "minProperties validation", "test": "exact length is valid", "schema": "minProperties/schema_0.json", "data": "minProperties/data_01.json", "valid": "true"}, - {"phase": "minProperties validation", "test": "too short is invalid", "schema": "minProperties/schema_0.json", "data": "minProperties/data_02.json", "valid": "false", "errors": "array_min_properties"}, - {"phase": "minProperties validation", "test": "ignores non-objects", "schema": "minProperties/schema_0.json", "data": "minProperties/data_03.json", "valid": "true"}, - {"phase": "maxProperties validation", "test": "shorter is valid", "schema": "maxProperties/schema_0.json", "data": "maxProperties/data_00.json", "valid": "true"}, - {"phase": "maxProperties validation", "test": "exact length is valid", "schema": "maxProperties/schema_0.json", "data": "maxProperties/data_01.json", "valid": "true"}, - {"phase": "maxProperties validation", "test": "too long is invalid", "schema": "maxProperties/schema_0.json", "data": "maxProperties/data_02.json", "valid": "false", "errors": "array_max_properties"}, - {"phase": "maxProperties validation", "test": "ignores non-objects", "schema": "maxProperties/schema_0.json", "data": "maxProperties/data_03.json", "valid": "true"}, - {"phase": "by int", "test": "int by int", "schema": "multipleOf/schema_0.json", "data": "multipleOf/data_00.json", "valid": "true"}, - {"phase": "by int", "test": "int by int fail", "schema": "multipleOf/schema_0.json", "data": "multipleOf/data_01.json", "valid": "false", "errors": "multiple_of"}, - {"phase": "by int", "test": "ignores non-numbers", "schema": "multipleOf/schema_0.json", "data": "multipleOf/data_02.json", "valid": "true"}, - {"phase": "by number", "test": "zero is multiple of anything", "schema": "multipleOf/schema_1.json", "data": "multipleOf/data_10.json", "valid": "true"}, - {"phase": "by number", "test": "4.5 is multiple of 1.5", "schema": "multipleOf/schema_1.json", "data": "multipleOf/data_11.json", "valid": "true"}, - {"phase": "by number", "test": "35 is not multiple of 1.5", "schema": "multipleOf/schema_1.json", "data": "multipleOf/data_12.json", "valid": "false", "errors": "multiple_of"}, - {"phase": "by small number", "test": "0.0075 is multiple of 0.0001", "schema": "multipleOf/schema_2.json", "data": "multipleOf/data_20.json", "valid": "true"}, - {"phase": "by small number", "test": "0.00751 is not multiple of 0.0001", "schema": "multipleOf/schema_2.json", "data": "multipleOf/data_21.json", "valid": "false", "errors": "multiple_of"}, - {"phase": "minItems validation", "test": "longer is valid", "schema": "minItems/schema_0.json", "data": "minItems/data_00.json", "valid": "true"}, - {"phase": "minItems validation", "test": "exact length is valid", "schema": "minItems/schema_0.json", "data": "minItems/data_01.json", "valid": "true"}, - {"phase": "minItems validation", "test": "too short is invalid", "schema": "minItems/schema_0.json", "data": "minItems/data_02.json", "valid": "false", "errors": "array_min_items"}, - {"phase": "minItems validation", "test": "ignores non-arrays", "schema": "minItems/schema_0.json", "data": "minItems/data_03.json", "valid": "true"}, - {"phase": "maxItems validation", "test": "shorter is valid", "schema": "maxItems/schema_0.json", "data": "maxItems/data_00.json", "valid": "true"}, - {"phase": "maxItems validation", "test": "exact length is valid", "schema": "maxItems/schema_0.json", "data": "maxItems/data_01.json", "valid": "true"}, - {"phase": "maxItems validation", "test": "too long is invalid", "schema": "maxItems/schema_0.json", "data": "maxItems/data_02.json", "valid": "false", "errors": "array_max_items"}, - {"phase": "maxItems validation", "test": "ignores non-arrays", "schema": "maxItems/schema_0.json", "data": "maxItems/data_03.json", "valid": "true"}, - {"phase": "object properties validation", "test": "both properties present and valid is valid", "schema": "properties/schema_0.json", "data": "properties/data_00.json", "valid": "true"}, - {"phase": "object properties validation", "test": "one property invalid is invalid", "schema": "properties/schema_0.json", "data": "properties/data_01.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "object properties validation", "test": "both properties invalid is invalid", "schema": "properties/schema_0.json", "data": "properties/data_02.json", "valid": "false", "errors": "invalid_type, invalid_type"}, - {"phase": "object properties validation", "test": "doesn't invalidate other properties", "schema": "properties/schema_0.json", "data": "properties/data_03.json", "valid": "true"}, - {"phase": "object properties validation", "test": "ignores non-objects", "schema": "properties/schema_0.json", "data": "properties/data_04.json", "valid": "true"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "property validates property", "schema": "properties/schema_1.json", "data": "properties/data_10.json", "valid": "true"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "property invalidates property", "schema": "properties/schema_1.json", "data": "properties/data_11.json", "valid": "false", "errors": "array_max_items"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "patternProperty invalidates property", "schema": "properties/schema_1.json", "data": "properties/data_12.json", "valid": "false", "errors": "array_min_items, invalid_type"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "patternProperty validates nonproperty", "schema": "properties/schema_1.json", "data": "properties/data_13.json", "valid": "true"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "patternProperty invalidates nonproperty", "schema": "properties/schema_1.json", "data": "properties/data_14.json", "valid": "false", "errors": "array_min_items, invalid_type"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "additionalProperty ignores property", "schema": "properties/schema_1.json", "data": "properties/data_15.json", "valid": "true"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "additionalProperty validates others", "schema": "properties/schema_1.json", "data": "properties/data_16.json", "valid": "true"}, - {"phase": "properties, patternProperties, additionalProperties interaction", "test": "additionalProperty invalidates others", "schema": "properties/schema_1.json", "data": "properties/data_17.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "root pointer ref", "test": "match", "schema": "ref/schema_0.json", "data": "ref/data_00.json", "valid": "true"}, - {"phase": "root pointer ref", "test": "recursive match", "schema": "ref/schema_0.json", "data": "ref/data_01.json", "valid": "true"}, - {"phase": "root pointer ref", "test": "mismatch", "schema": "ref/schema_0.json", "data": "ref/data_02.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "root pointer ref", "test": "recursive mismatch", "schema": "ref/schema_0.json", "data": "ref/data_03.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "loader pointer ref", "test": "root ref valid", "schema": "ref/schema_6.json#/definitions/x", "data": "ref/data_40.json", "valid": "true"}, - {"phase": "loader pointer ref", "test": "root ref invalid", "schema": "ref/schema_6.json#/definitions/x", "data": "ref/data_41.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "relative pointer ref to object", "test": "match", "schema": "ref/schema_1.json", "data": "ref/data_10.json", "valid": "true"}, - {"phase": "relative pointer ref to object", "test": "mismatch", "schema": "ref/schema_1.json", "data": "ref/data_11.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "relative pointer ref to array", "test": "match array", "schema": "ref/schema_2.json", "data": "ref/data_20.json", "valid": "true"}, - {"phase": "relative pointer ref to array", "test": "mismatch array", "schema": "ref/schema_2.json", "data": "ref/data_21.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "escaped pointer ref", "test": "slash", "schema": "ref/schema_3.json", "data": "ref/data_30.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "escaped pointer ref", "test": "tilda", "schema": "ref/schema_3.json", "data": "ref/data_31.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "escaped pointer ref", "test": "percent", "schema": "ref/schema_3.json", "data": "ref/data_32.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "nested refs", "test": "nested ref valid", "schema": "ref/schema_4.json", "data": "ref/data_40.json", "valid": "true"}, - {"phase": "nested refs", "test": "nested ref invalid", "schema": "ref/schema_4.json", "data": "ref/data_41.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "remote ref, containing refs itself", "test": "remote ref valid", "schema": "ref/schema_5.json", "data": "ref/data_50.json", "valid": "true"}, - {"phase": "remote ref, containing refs itself", "test": "remote ref invalid", "schema": "ref/schema_5.json", "data": "ref/data_51.json", "valid": "false", "errors": "number_all_of, number_gte"}, - {"phase": "a schema given for items", "test": "valid items", "schema": "items/schema_0.json", "data": "items/data_00.json", "valid": "true"}, - {"phase": "a schema given for items", "test": "wrong type of items", "schema": "items/schema_0.json", "data": "items/data_01.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "a schema given for items", "test": "ignores non-arrays", "schema": "items/schema_0.json", "data": "items/data_02.json", "valid": "true"}, - {"phase": "an array of schemas for items", "test": "correct types", "schema": "items/schema_1.json", "data": "items/data_10.json", "valid": "true"}, - {"phase": "an array of schemas for items", "test": "wrong types", "schema": "items/schema_1.json", "data": "items/data_11.json", "valid": "false", "errors": "invalid_type, invalid_type"}, - {"phase": "valid definition", "test": "valid definition schema", "schema": "definitions/schema_0.json", "data": "definitions/data_00.json", "valid": "true"}, - {"phase": "invalid definition", "test": "invalid definition schema", "schema": "definitions/schema_1.json", "data": "definitions/data_10.json", "valid": "false", "errors": "number_any_of, enum"}, - {"phase": "additionalItems as schema", "test": "additional items match schema", "schema": "additionalItems/schema_0.json", "data": "additionalItems/data_00.json", "valid": "true"}, - {"phase": "additionalItems as schema", "test": "additional items do not match schema", "schema": "additionalItems/schema_0.json", "data": "additionalItems/data_01.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "items is schema, no additionalItems", "test": "all items match schema", "schema": "additionalItems/schema_1.json", "data": "additionalItems/data_10.json", "valid": "true"}, - {"phase": "array of items with no additionalItems", "test": "no additional items present", "schema": "additionalItems/schema_2.json", "data": "additionalItems/data_20.json", "valid": "true"}, - {"phase": "array of items with no additionalItems", "test": "additional items are not permitted", "schema": "additionalItems/schema_2.json", "data": "additionalItems/data_21.json", "valid": "false", "errors": "array_no_additional_items"}, - {"phase": "additionalItems as false without items", "test": "items defaults to empty schema so everything is valid", "schema": "additionalItems/schema_3.json", "data": "additionalItems/data_30.json", "valid": "true"}, - {"phase": "additionalItems as false without items", "test": "ignores non-arrays", "schema": "additionalItems/schema_3.json", "data": "additionalItems/data_31.json", "valid": "true"}, - {"phase": "additionalItems are allowed by default", "test": "only the first item is validated", "schema": "additionalItems/schema_4.json", "data": "additionalItems/data_40.json", "valid": "true"}, - {"phase": "additionalProperties being false does not allow other properties", "test": "no additional properties is valid", "schema": "additionalProperties/schema_0.json", "data": "additionalProperties/data_00.json", "valid": "true"}, - {"phase": "additionalProperties being false does not allow other properties", "test": "an additional property is invalid", "schema": "additionalProperties/schema_0.json", "data": "additionalProperties/data_01.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "additionalProperties being false does not allow other properties", "test": "ignores non-objects", "schema": "additionalProperties/schema_0.json", "data": "additionalProperties/data_02.json", "valid": "true"}, - {"phase": "additionalProperties being false does not allow other properties", "test": "patternProperties are not additional properties", "schema": "additionalProperties/schema_0.json", "data": "additionalProperties/data_03.json", "valid": "true"}, - {"phase": "additionalProperties allows a schema which should validate", "test": "no additional properties is valid", "schema": "additionalProperties/schema_1.json", "data": "additionalProperties/data_10.json", "valid": "true"}, - {"phase": "additionalProperties allows a schema which should validate", "test": "an additional valid property is valid", "schema": "additionalProperties/schema_1.json", "data": "additionalProperties/data_11.json", "valid": "true"}, - {"phase": "additionalProperties allows a schema which should validate", "test": "an additional invalid property is invalid", "schema": "additionalProperties/schema_1.json", "data": "additionalProperties/data_12.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "additionalProperties are allowed by default", "test": "additional properties are allowed", "schema": "additionalProperties/schema_2.json", "data": "additionalProperties/data_20.json", "valid": "true"}, - {"phase": "dependencies", "test": "neither", "schema": "dependencies/schema_0.json", "data": "dependencies/data_00.json", "valid": "true"}, - {"phase": "dependencies", "test": "nondependant", "schema": "dependencies/schema_0.json", "data": "dependencies/data_01.json", "valid": "true"}, - {"phase": "dependencies", "test": "with dependency", "schema": "dependencies/schema_0.json", "data": "dependencies/data_02.json", "valid": "true"}, - {"phase": "dependencies", "test": "missing dependency", "schema": "dependencies/schema_0.json", "data": "dependencies/data_03.json", "valid": "false", "errors": "missing_dependency"}, - {"phase": "dependencies", "test": "ignores non-objects", "schema": "dependencies/schema_0.json", "data": "dependencies/data_04.json", "valid": "true"}, - {"phase": "multiple dependencies", "test": "neither", "schema": "dependencies/schema_1.json", "data": "dependencies/data_10.json", "valid": "true"}, - {"phase": "multiple dependencies", "test": "nondependants", "schema": "dependencies/schema_1.json", "data": "dependencies/data_11.json", "valid": "true"}, - {"phase": "multiple dependencies", "test": "with dependencies", "schema": "dependencies/schema_1.json", "data": "dependencies/data_12.json", "valid": "true"}, - {"phase": "multiple dependencies", "test": "missing dependency", "schema": "dependencies/schema_1.json", "data": "dependencies/data_13.json", "valid": "false", "errors": "missing_dependency"}, - {"phase": "multiple dependencies", "test": "missing other dependency", "schema": "dependencies/schema_1.json", "data": "dependencies/data_14.json", "valid": "false", "errors": "missing_dependency"}, - {"phase": "multiple dependencies", "test": "missing both dependencies", "schema": "dependencies/schema_1.json", "data": "dependencies/data_15.json", "valid": "false", "errors": "missing_dependency, missing_dependency"}, - {"phase": "multiple dependencies subschema", "test": "valid", "schema": "dependencies/schema_2.json", "data": "dependencies/data_20.json", "valid": "true"}, - {"phase": "multiple dependencies subschema", "test": "no dependency", "schema": "dependencies/schema_2.json", "data": "dependencies/data_21.json", "valid": "true"}, - {"phase": "multiple dependencies subschema", "test": "wrong type", "schema": "dependencies/schema_2.json", "data": "dependencies/data_22.json", "valid": "false"}, - {"phase": "multiple dependencies subschema", "test": "wrong type other", "schema": "dependencies/schema_2.json", "data": "dependencies/data_23.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "multiple dependencies subschema", "test": "wrong type both", "schema": "dependencies/schema_2.json", "data": "dependencies/data_24.json", "valid": "false", "errors": "invalid_type, invalid_type"}, - {"phase": "patternProperties validates properties matching a regex", "test": "a single valid match is valid", "schema": "patternProperties/schema_0.json", "data": "patternProperties/data_00.json", "valid": "true"}, - {"phase": "patternProperties validates properties matching a regex", "test": "multiple valid matches is valid", "schema": "patternProperties/schema_0.json", "data": "patternProperties/data_01.json", "valid": "true"}, - {"phase": "patternProperties validates properties matching a regex", "test": "a single invalid match is invalid", "schema": "patternProperties/schema_0.json", "data": "patternProperties/data_02.json", "valid": "false", "errors": "invalid_property_pattern, invalid_type"}, - {"phase": "patternProperties validates properties matching a regex", "test": "multiple invalid matches is invalid", "schema": "patternProperties/schema_0.json", "data": "patternProperties/data_03.json", "valid": "false", "errors": "invalid_property_pattern, invalid_property_pattern, invalid_type, invalid_type"}, - {"phase": "patternProperties validates properties matching a regex", "test": "ignores non-objects", "schema": "patternProperties/schema_0.json", "data": "patternProperties/data_04.json", "valid": "true"}, - {"phase": "patternProperties validates properties matching a regex", "test": "with additionalProperties combination", "schema": "patternProperties/schema_3.json", "data": "patternProperties/data_24.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "patternProperties validates properties matching a regex", "test": "with additionalProperties combination", "schema": "patternProperties/schema_3.json", "data": "patternProperties/data_25.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "patternProperties validates properties matching a regex", "test": "with additionalProperties combination", "schema": "patternProperties/schema_4.json", "data": "patternProperties/data_26.json", "valid": "false", "errors": "additional_property_not_allowed"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "a single valid match is valid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_10.json", "valid": "true"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "a simultaneous match is valid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_11.json", "valid": "true"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "multiple matches is valid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_12.json", "valid": "true"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "an invalid due to one is invalid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_13.json", "valid": "false", "errors": "invalid_property_pattern, invalid_type"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "an invalid due to the other is invalid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_14.json", "valid": "false", "errors": "number_lte"}, - {"phase": "multiple simultaneous patternProperties are validated", "test": "an invalid due to both is invalid", "schema": "patternProperties/schema_1.json", "data": "patternProperties/data_15.json", "valid": "false", "errors": "invalid_type, number_lte"}, - {"phase": "regexes are not anchored by default and are case sensitive", "test": "non recognized members are ignored", "schema": "patternProperties/schema_2.json", "data": "patternProperties/data_20.json", "valid": "true"}, - {"phase": "regexes are not anchored by default and are case sensitive", "test": "recognized members are accounted for", "schema": "patternProperties/schema_2.json", "data": "patternProperties/data_21.json", "valid": "false", "errors": "invalid_property_pattern, invalid_type"}, - {"phase": "regexes are not anchored by default and are case sensitive", "test": "regexes are case sensitive", "schema": "patternProperties/schema_2.json", "data": "patternProperties/data_22.json", "valid": "true"}, - {"phase": "regexes are not anchored by default and are case sensitive", "test": "regexes are case sensitive, 2", "schema": "patternProperties/schema_2.json", "data": "patternProperties/data_23.json", "valid": "false", "errors": "invalid_property_pattern, invalid_type"}, - {"phase": "remote ref", "test": "remote ref valid", "schema": "refRemote/schema_0.json", "data": "refRemote/data_00.json", "valid": "true"}, - {"phase": "remote ref", "test": "remote ref invalid", "schema": "refRemote/schema_0.json", "data": "refRemote/data_01.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "fragment within remote ref", "test": "remote fragment valid", "schema": "refRemote/schema_1.json", "data": "refRemote/data_10.json", "valid": "true"}, - {"phase": "fragment within remote ref", "test": "remote fragment invalid", "schema": "refRemote/schema_1.json", "data": "refRemote/data_11.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "ref within remote ref", "test": "ref within ref valid", "schema": "refRemote/schema_2.json", "data": "refRemote/data_20.json", "valid": "true"}, - {"phase": "ref within remote ref", "test": "ref within ref invalid", "schema": "refRemote/schema_2.json", "data": "refRemote/data_21.json", "valid": "false", "errors": "invalid_type"}, - {"phase": "format validation", "test": "email format is invalid", "schema": "format/schema_0.json", "data": "format/data_00.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "email format is invalid", "schema": "format/schema_0.json", "data": "format/data_01.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "email format valid", "schema": "format/schema_0.json", "data": "format/data_02.json", "valid": "true"}, - {"phase": "format validation", "test": "invoice format valid", "schema": "format/schema_1.json", "data": "format/data_03.json", "valid": "true"}, - {"phase": "format validation", "test": "invoice format is invalid", "schema": "format/schema_1.json", "data": "format/data_04.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_05.json", "valid": "true"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_06.json", "valid": "true"}, - {"phase": "format validation", "test": "date-time format is invalid", "schema": "format/schema_2.json", "data": "format/data_07.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_08.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_09.json", "valid": "true"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_10.json", "valid": "true"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_11.json", "valid": "true"}, - {"phase": "format validation", "test": "date-time format is valid", "schema": "format/schema_2.json", "data": "format/data_12.json", "valid": "true"}, - {"phase": "format validation", "test": "hostname format is valid", "schema": "format/schema_3.json", "data": "format/data_13.json", "valid": "true"}, - {"phase": "format validation", "test": "hostname format is valid", "schema": "format/schema_3.json", "data": "format/data_14.json", "valid": "true"}, - {"phase": "format validation", "test": "hostname format is valid", "schema": "format/schema_3.json", "data": "format/data_15.json", "valid": "true"}, - {"phase": "format validation", "test": "hostname format is invalid", "schema": "format/schema_3.json", "data": "format/data_16.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "hostname format is invalid", "schema": "format/schema_3.json", "data": "format/data_17.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "ipv4 format is valid", "schema": "format/schema_4.json", "data": "format/data_18.json", "valid": "true"}, - {"phase": "format validation", "test": "ipv4 format is invalid", "schema": "format/schema_4.json", "data": "format/data_19.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "ipv6 format is valid", "schema": "format/schema_5.json", "data": "format/data_20.json", "valid": "true"}, - {"phase": "format validation", "test": "ipv6 format is valid", "schema": "format/schema_5.json", "data": "format/data_21.json", "valid": "true"}, - {"phase": "format validation", "test": "ipv6 format is invalid", "schema": "format/schema_5.json", "data": "format/data_22.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "ipv6 format is invalid", "schema": "format/schema_5.json", "data": "format/data_23.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "uri format is valid", "schema": "format/schema_6.json", "data": "format/data_24.json", "valid": "true"}, - {"phase": "format validation", "test": "uri format is valid", "schema": "format/schema_6.json", "data": "format/data_25.json", "valid": "true"}, - {"phase": "format validation", "test": "uri format is valid", "schema": "format/schema_6.json", "data": "format/data_26.json", "valid": "true"}, - {"phase": "format validation", "test": "uri format is valid", "schema": "format/schema_6.json", "data": "format/data_27.json", "valid": "true"}, - {"phase": "format validation", "test": "uri format is invalid", "schema": "format/schema_6.json", "data": "format/data_28.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "uri format is invalid", "schema": "format/schema_6.json", "data": "format/data_13.json", "valid": "false", "errors": "format"}, - {"phase": "format validation", "test": "number format is valid", "schema": "format/schema_7.json", "data": "format/data_29.json", "valid": "true"}, - {"phase": "format validation", "test": "number format is valid", "schema": "format/schema_7.json", "data": "format/data_30.json", "valid": "false", "errors": "format"}, - {"phase": "change resolution scope", "test": "changed scope ref valid", "schema": "refRemote/schema_3.json", "data": "refRemote/data_30.json", "valid": "true"}, - {"phase": "change resolution scope", "test": "changed scope ref invalid", "schema": "refRemote/schema_3.json", "data": "refRemote/data_31.json", "valid": "false", "errors": "invalid_type"}, - } - - // Setup a small http server on localhost:1234 for testing purposes - - wd, err := os.Getwd() - if err != nil { - panic(err.Error()) - } - - testwd := wd + "/json_schema_test_suite" - - go func() { - err := http.ListenAndServe(":1234", http.FileServer(http.Dir(testwd+"/refRemote/remoteFiles"))) - if err != nil { - panic(err.Error()) - } - }() - - // Used for remote schema in ref/schema_5.json that defines "regex" type - FormatCheckers.Add("regex", alwaysTrueFormatChecker{}) - - // Custom Formatter - FormatCheckers.Add("invoice", invoiceFormatChecker{}) - - // Number Formatter - FormatCheckers.Add("evenNumber", evenNumberFormatChecker{}) - - // Launch tests - - for testJsonIndex, testJson := range JsonSchemaTestSuiteMap { - - fmt.Printf("Test (%d) | %s :: %s\n", testJsonIndex, testJson["phase"], testJson["test"]) - - schemaLoader := NewReferenceLoader("file://" + testwd + "/" + testJson["schema"]) - documentLoader := NewReferenceLoader("file://" + testwd + "/" + testJson["data"]) - - // validate - result, err := Validate(schemaLoader, documentLoader) - if err != nil { - t.Errorf("Error (%s)\n", err.Error()) - } - givenValid := result.Valid() - - if displayErrorMessages { - for vErrI, vErr := range result.Errors() { - fmt.Printf(" Error (%d) | %s\n", vErrI, vErr) - } - } - - expectedValid, _ := strconv.ParseBool(testJson["valid"]) - if givenValid != expectedValid { - t.Errorf("Test failed : %s :: %s, expects %t, given %t\n", testJson["phase"], testJson["test"], expectedValid, givenValid) - for _, e := range result.Errors() { - fmt.Println("Error: " + e.Type()) - } - } - - if !givenValid && testJson["errors"] != "" { - expectedErrors := rxSplitErrors.Split(testJson["errors"], -1) - errors := result.Errors() - if len(errors) != len(expectedErrors) { - t.Errorf("Test failed : %s :: %s, expects %d errors, given %d errors\n", testJson["phase"], testJson["test"], len(expectedErrors), len(errors)) - } - - actualErrors := make([]string, 0) - for _, e := range result.Errors() { - actualErrors = append(actualErrors, e.Type()) - } - - sort.Strings(actualErrors) - sort.Strings(expectedErrors) - if !reflect.DeepEqual(actualErrors, expectedErrors) { - t.Errorf("Test failed : %s :: %s, expected '%s' errors, given '%s' errors\n", testJson["phase"], testJson["test"], strings.Join(expectedErrors, ", "), strings.Join(actualErrors, ", ")) - } - } - - } - - fmt.Printf("\n%d tests performed / %d total tests to perform ( %.2f %% )\n", len(JsonSchemaTestSuiteMap), 248, float32(len(JsonSchemaTestSuiteMap))/248.0*100.0) -} - const circularReference = `{ "type": "object", "properties": { @@ -590,3 +184,148 @@ func TestLoadersWithInvalidPattern(t *testing.T) { assert.NotNil(t, err, "expected error loading invalid pattern: %T", l) } } + +const refPropertySchema = `{ + "$id" : "http://localhost/schema.json", + "properties" : { + "$id" : { + "$id": "http://localhost/foo.json" + }, + "$ref" : { + "const": { + "$ref" : "hello.world" + } + }, + "const" : { + "$ref" : "#/definitions/$ref" + } + }, + "definitions" : { + "$ref" : { + "const": { + "$ref" : "hello.world" + } + } + }, + "dependencies" : { + "$ref" : [ "const" ], + "const" : [ "$ref" ] + } +}` + +func TestRefProperty(t *testing.T) { + schemaLoader := NewStringLoader(refPropertySchema) + documentLoader := NewStringLoader(`{ + "$ref" : { "$ref" : "hello.world" }, + "const" : { "$ref" : "hello.world" } + }`) + // call the target function + s, err := NewSchema(schemaLoader) + if err != nil { + t.Errorf("Got error: %s", err.Error()) + } + result, err := s.Validate(documentLoader) + if err != nil { + t.Errorf("Got error: %s", err.Error()) + } + if !result.Valid() { + for _, err := range result.Errors() { + fmt.Println(err.String()) + } + t.Errorf("Got invalid validation result.") + } +} + +func TestFragmentLoader(t *testing.T) { + wd, err := os.Getwd() + + if err != nil { + panic(err.Error()) + } + + fileName := filepath.Join(wd, "testdata", "extra", "fragment_schema.json") + + schemaLoader := NewReferenceLoader("file://" + fileName + "#/definitions/x") + schema, err := NewSchema(schemaLoader) + + if err != nil { + t.Errorf("Encountered error while loading schema: %s", err.Error()) + } + + validDocument := NewStringLoader(`5`) + invalidDocument := NewStringLoader(`"a"`) + + result, err := schema.Validate(validDocument) + + if assert.Nil(t, err, "Unexpected error while validating document: %T", err) { + if !result.Valid() { + t.Errorf("Got invalid validation result.") + } + } + + result, err = schema.Validate(invalidDocument) + + if assert.Nil(t, err, "Unexpected error while validating document: %T", err) { + if len(result.Errors()) != 1 || result.Errors()[0].Type() != "invalid_type" { + t.Errorf("Got invalid validation result.") + } + } +} + +// Inspired by http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3 +const locationIndependentSchema = `{ + "definitions": { + "A": { + "$id": "#foo" + }, + "B": { + "$id": "http://example.com/other.json", + "definitions": { + "X": { + "$id": "#bar", + "allOf": [false] + }, + "Y": { + "$id": "t/inner.json" + } + } + }, + "C": { + "$id" : "#frag", + "$ref": "http://example.com/other.json#bar" + } + }, + "$ref": "#frag" +}` + +func TestLocationIndependentIdentifier(t *testing.T) { + schemaLoader := NewStringLoader(locationIndependentSchema) + documentLoader := NewStringLoader(`{}`) + + s, err := NewSchema(schemaLoader) + if err != nil { + t.Errorf("Got error: %s", err.Error()) + } + + result, err := s.Validate(documentLoader) + if err != nil { + t.Errorf("Got error: %s", err.Error()) + } + + if len(result.Errors()) != 2 || result.Errors()[0].Type() != "number_not" || result.Errors()[1].Type() != "number_all_of" { + t.Errorf("Got invalid validation result.") + } +} + +const incorrectRefSchema = `{ + "$ref" : "#/fail" +}` + +func TestIncorrectRef(t *testing.T) { + + schemaLoader := NewStringLoader(incorrectRefSchema) + s, err := NewSchema(schemaLoader) + + assert.Nil(t, s) + assert.Equal(t, "Object has no key 'fail'", err.Error()) +} diff --git a/vendor/github.com/xeipuuv/gojsonschema/subSchema.go b/vendor/github.com/xeipuuv/gojsonschema/subSchema.go index 9961d92..ea792a1 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/subSchema.go +++ b/vendor/github.com/xeipuuv/gojsonschema/subSchema.go @@ -28,6 +28,7 @@ package gojsonschema import ( "errors" + "math/big" "regexp" "strings" @@ -35,8 +36,9 @@ import ( ) const ( - KEY_SCHEMA = "$subSchema" + KEY_SCHEMA = "$schema" KEY_ID = "id" + KEY_ID_NEW = "$id" KEY_REF = "$ref" KEY_TITLE = "title" KEY_DESCRIPTION = "description" @@ -46,6 +48,7 @@ const ( KEY_PROPERTIES = "properties" KEY_PATTERN_PROPERTIES = "patternProperties" KEY_ADDITIONAL_PROPERTIES = "additionalProperties" + KEY_PROPERTY_NAMES = "propertyNames" KEY_DEFINITIONS = "definitions" KEY_MULTIPLE_OF = "multipleOf" KEY_MINIMUM = "minimum" @@ -63,11 +66,16 @@ const ( KEY_MIN_ITEMS = "minItems" KEY_MAX_ITEMS = "maxItems" KEY_UNIQUE_ITEMS = "uniqueItems" + KEY_CONTAINS = "contains" + KEY_CONST = "const" KEY_ENUM = "enum" KEY_ONE_OF = "oneOf" KEY_ANY_OF = "anyOf" KEY_ALL_OF = "allOf" KEY_NOT = "not" + KEY_IF = "if" + KEY_THEN = "then" + KEY_ELSE = "else" ) type subSchema struct { @@ -86,22 +94,18 @@ type subSchema struct { ref *gojsonreference.JsonReference // Schema referenced refSchema *subSchema - // Json reference - subSchema *gojsonreference.JsonReference // hierarchy parent *subSchema - definitions map[string]*subSchema - definitionsChildren []*subSchema itemsChildren []*subSchema itemsChildrenIsSingleSchema bool propertiesChildren []*subSchema // validation : number / integer - multipleOf *float64 - maximum *float64 + multipleOf *big.Float + maximum *big.Float exclusiveMaximum bool - minimum *float64 + minimum *big.Float exclusiveMinimum bool // validation : string @@ -118,27 +122,43 @@ type subSchema struct { dependencies map[string]interface{} additionalProperties interface{} patternProperties map[string]*subSchema + propertyNames *subSchema // validation : array minItems *int maxItems *int uniqueItems bool + contains *subSchema additionalItems interface{} // validation : all - enum []string + _const *string //const is a golang keyword + enum []string // validation : subSchema oneOf []*subSchema anyOf []*subSchema allOf []*subSchema not *subSchema + _if *subSchema // if/else are golang keywords + _then *subSchema + _else *subSchema +} + +func (s *subSchema) AddConst(i interface{}) error { + + is, err := marshalWithoutNumber(i) + if err != nil { + return err + } + s._const = is + return nil } func (s *subSchema) AddEnum(i interface{}) error { - is, err := marshalToJsonString(i) + is, err := marshalWithoutNumber(i) if err != nil { return err } @@ -157,7 +177,7 @@ func (s *subSchema) AddEnum(i interface{}) error { func (s *subSchema) ContainsEnum(i interface{}) (bool, error) { - is, err := marshalToJsonString(i) + is, err := marshalWithoutNumber(i) if err != nil { return false, err } @@ -181,6 +201,18 @@ func (s *subSchema) SetNot(subSchema *subSchema) { s.not = subSchema } +func (s *subSchema) SetIf(subSchema *subSchema) { + s._if = subSchema +} + +func (s *subSchema) SetThen(subSchema *subSchema) { + s._then = subSchema +} + +func (s *subSchema) SetElse(subSchema *subSchema) { + s._else = subSchema +} + func (s *subSchema) AddRequired(value string) error { if isStringInSlice(s.required, value) { @@ -195,10 +227,6 @@ func (s *subSchema) AddRequired(value string) error { return nil } -func (s *subSchema) AddDefinitionChild(child *subSchema) { - s.definitionsChildren = append(s.definitionsChildren, child) -} - func (s *subSchema) AddItemsChild(child *subSchema) { s.itemsChildren = append(s.itemsChildren, child) } diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalItems.json new file mode 100644 index 0000000..abecc57 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalItems.json @@ -0,0 +1,87 @@ +[ + { + "description": "additionalItems as schema", + "schema": { + "items": [{}], + "additionalItems": {"type": "integer"} + }, + "tests": [ + { + "description": "additional items match schema", + "data": [ null, 2, 3, 4 ], + "valid": true + }, + { + "description": "additional items do not match schema", + "data": [ null, 2, 3, "foo" ], + "valid": false + } + ] + }, + { + "description": "items is schema, no additionalItems", + "schema": { + "items": {}, + "additionalItems": false + }, + "tests": [ + { + "description": "all items match schema", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + } + ] + }, + { + "description": "array of items with no additionalItems", + "schema": { + "items": [{}, {}, {}], + "additionalItems": false + }, + "tests": [ + { + "description": "fewer number of items present", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "equal number of items present", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "additional items are not permitted", + "data": [ 1, 2, 3, 4 ], + "valid": false + } + ] + }, + { + "description": "additionalItems as false without items", + "schema": {"additionalItems": false}, + "tests": [ + { + "description": + "items defaults to empty schema so everything is valid", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + } + ] + }, + { + "description": "additionalItems are allowed by default", + "schema": {"items": [{"type": "integer"}]}, + "tests": [ + { + "description": "only the first item is validated", + "data": [1, "foo", false], + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalProperties.json new file mode 100644 index 0000000..90d7607 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/additionalProperties.json @@ -0,0 +1,98 @@ +[ + { + "description": + "additionalProperties being false does not allow other properties", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "patternProperties": { "^v": {} }, + "additionalProperties": false + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobarbaz", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + }, + { + "description": "patternProperties are not additional properties", + "data": {"foo":1, "vroom": 2}, + "valid": true + } + ] + }, + { + "description": + "additionalProperties allows a schema which should validate", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional valid property is valid", + "data": {"foo" : 1, "bar" : 2, "quux" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : 12}, + "valid": false + } + ] + }, + { + "description": + "additionalProperties can exist by itself", + "schema": { + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "an additional valid property is valid", + "data": {"foo" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1}, + "valid": false + } + ] + }, + { + "description": "additionalProperties are allowed by default", + "schema": {"properties": {"foo": {}, "bar": {}}}, + "tests": [ + { + "description": "additional properties are allowed", + "data": {"foo": 1, "bar": 2, "quux": true}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/allOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/allOf.json new file mode 100644 index 0000000..bbb5f89 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/allOf.json @@ -0,0 +1,112 @@ +[ + { + "description": "allOf", + "schema": { + "allOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "allOf", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "mismatch second", + "data": {"foo": "baz"}, + "valid": false + }, + { + "description": "mismatch first", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "wrong type", + "data": {"foo": "baz", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "allOf with base schema", + "schema": { + "properties": {"bar": {"type": "integer"}}, + "required": ["bar"], + "allOf" : [ + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + }, + { + "properties": { + "baz": {"type": "null"} + }, + "required": ["baz"] + } + ] + }, + "tests": [ + { + "description": "valid", + "data": {"foo": "quux", "bar": 2, "baz": null}, + "valid": true + }, + { + "description": "mismatch base schema", + "data": {"foo": "quux", "baz": null}, + "valid": false + }, + { + "description": "mismatch first allOf", + "data": {"bar": 2, "baz": null}, + "valid": false + }, + { + "description": "mismatch second allOf", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "mismatch both", + "data": {"bar": 2}, + "valid": false + } + ] + }, + { + "description": "allOf simple types", + "schema": { + "allOf": [ + {"maximum": 30}, + {"minimum": 20} + ] + }, + "tests": [ + { + "description": "valid", + "data": 25, + "valid": true + }, + { + "description": "mismatch one", + "data": 35, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/anyOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/anyOf.json new file mode 100644 index 0000000..6c8b251 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/anyOf.json @@ -0,0 +1,109 @@ +[ + { + "description": "anyOf", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first anyOf valid", + "data": 1, + "valid": true + }, + { + "description": "second anyOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both anyOf valid", + "data": 3, + "valid": true + }, + { + "description": "neither anyOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "anyOf with base schema", + "schema": { + "type": "string", + "anyOf" : [ + { + "maxLength": 2 + }, + { + "minLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one anyOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both anyOf invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf complex types", + "schema": { + "anyOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first anyOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second anyOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both anyOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "neither anyOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/default.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/default.json new file mode 100644 index 0000000..1762977 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/default.json @@ -0,0 +1,49 @@ +[ + { + "description": "invalid type for default", + "schema": { + "properties": { + "foo": { + "type": "integer", + "default": [] + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"foo": 13}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + }, + { + "description": "invalid string value for default", + "schema": { + "properties": { + "bar": { + "type": "string", + "minLength": 4, + "default": "bad" + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"bar": "good"}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/definitions.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/definitions.json new file mode 100644 index 0000000..cf935a3 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/definitions.json @@ -0,0 +1,32 @@ +[ + { + "description": "valid definition", + "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, + "tests": [ + { + "description": "valid definition schema", + "data": { + "definitions": { + "foo": {"type": "integer"} + } + }, + "valid": true + } + ] + }, + { + "description": "invalid definition", + "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, + "tests": [ + { + "description": "invalid definition schema", + "data": { + "definitions": { + "foo": {"type": 1} + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/dependencies.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/dependencies.json new file mode 100644 index 0000000..38effa1 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/dependencies.json @@ -0,0 +1,123 @@ +[ + { + "description": "dependencies", + "schema": { + "dependencies": {"bar": ["foo"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependant", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "with dependency", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "multiple dependencies", + "schema": { + "dependencies": {"quux": ["foo", "bar"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependants", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "with dependencies", + "data": {"foo": 1, "bar": 2, "quux": 3}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"foo": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing other dependency", + "data": {"bar": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing both dependencies", + "data": {"quux": 1}, + "valid": false + } + ] + }, + { + "description": "multiple dependencies subschema", + "schema": { + "dependencies": { + "bar": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "integer"} + } + } + } + }, + "tests": [ + { + "description": "valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "no dependency", + "data": {"foo": "quux"}, + "valid": true + }, + { + "description": "wrong type", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/enum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/enum.json new file mode 100644 index 0000000..f124436 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/enum.json @@ -0,0 +1,72 @@ +[ + { + "description": "simple enum validation", + "schema": {"enum": [1, 2, 3]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": 1, + "valid": true + }, + { + "description": "something else is invalid", + "data": 4, + "valid": false + } + ] + }, + { + "description": "heterogeneous enum validation", + "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": [], + "valid": true + }, + { + "description": "something else is invalid", + "data": null, + "valid": false + }, + { + "description": "objects are deep compared", + "data": {"foo": false}, + "valid": false + } + ] + }, + { + "description": "enums in properties", + "schema": { + "type":"object", + "properties": { + "foo": {"enum":["foo"]}, + "bar": {"enum":["bar"]} + }, + "required": ["bar"] + }, + "tests": [ + { + "description": "both properties are valid", + "data": {"foo":"foo", "bar":"bar"}, + "valid": true + }, + { + "description": "missing optional property is valid", + "data": {"bar":"bar"}, + "valid": true + }, + { + "description": "missing required property is invalid", + "data": {"foo":"foo"}, + "valid": false + }, + { + "description": "missing all properties is invalid", + "data": {}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/items.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/items.json new file mode 100644 index 0000000..6a4e648 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/items.json @@ -0,0 +1,78 @@ +[ + { + "description": "a schema given for items", + "schema": { + "items": {"type": "integer"} + }, + "tests": [ + { + "description": "valid items", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "wrong type of items", + "data": [1, "x"], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "length": 1 + }, + "valid": true + } + ] + }, + { + "description": "an array of schemas for items", + "schema": { + "items": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": false + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxItems.json new file mode 100644 index 0000000..3b53a6b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "maxItems validation", + "schema": {"maxItems": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": [1], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "too long is invalid", + "data": [1, 2, 3], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "foobar", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxLength.json new file mode 100644 index 0000000..811d35b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "maxLength validation", + "schema": {"maxLength": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too long is invalid", + "data": "foo", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + }, + { + "description": "two supplementary Unicode code points is long enough", + "data": "\uD83D\uDCA9\uD83D\uDCA9", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxProperties.json new file mode 100644 index 0000000..513731e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maxProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "maxProperties validation", + "schema": {"maxProperties": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "too long is invalid", + "data": {"foo": 1, "bar": 2, "baz": 3}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maximum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maximum.json new file mode 100644 index 0000000..82718fb --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/maximum.json @@ -0,0 +1,47 @@ +[ + { + "description": "maximum validation", + "schema": {"maximum": 3.0}, + "tests": [ + { + "description": "below the maximum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 3.0, + "valid": true + }, + { + "description": "above the maximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + }, + { + "description": "exclusiveMaximum validation", + "schema": { + "maximum": 3.0, + "exclusiveMaximum": true + }, + "tests": [ + { + "description": "below the maximum is still valid", + "data": 2.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 3.0, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minItems.json new file mode 100644 index 0000000..ed51188 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "minItems validation", + "schema": {"minItems": 1}, + "tests": [ + { + "description": "longer is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1], + "valid": true + }, + { + "description": "too short is invalid", + "data": [], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minLength.json new file mode 100644 index 0000000..3f09158 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "minLength validation", + "schema": {"minLength": 2}, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too short is invalid", + "data": "f", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 1, + "valid": true + }, + { + "description": "one supplementary Unicode code point is not long enough", + "data": "\uD83D\uDCA9", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minProperties.json new file mode 100644 index 0000000..49a0726 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "minProperties validation", + "schema": {"minProperties": 1}, + "tests": [ + { + "description": "longer is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "too short is invalid", + "data": {}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minimum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minimum.json new file mode 100644 index 0000000..9af8ed4 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/minimum.json @@ -0,0 +1,47 @@ +[ + { + "description": "minimum validation", + "schema": {"minimum": 1.1}, + "tests": [ + { + "description": "above the minimum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 1.1, + "valid": true + }, + { + "description": "below the minimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + }, + { + "description": "exclusiveMinimum validation", + "schema": { + "minimum": 1.1, + "exclusiveMinimum": true + }, + "tests": [ + { + "description": "above the minimum is still valid", + "data": 1.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 1.1, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/multipleOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/multipleOf.json new file mode 100644 index 0000000..ca3b761 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/multipleOf.json @@ -0,0 +1,60 @@ +[ + { + "description": "by int", + "schema": {"multipleOf": 2}, + "tests": [ + { + "description": "int by int", + "data": 10, + "valid": true + }, + { + "description": "int by int fail", + "data": 7, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "by number", + "schema": {"multipleOf": 1.5}, + "tests": [ + { + "description": "zero is multiple of anything", + "data": 0, + "valid": true + }, + { + "description": "4.5 is multiple of 1.5", + "data": 4.5, + "valid": true + }, + { + "description": "35 is not multiple of 1.5", + "data": 35, + "valid": false + } + ] + }, + { + "description": "by small number", + "schema": {"multipleOf": 0.0001}, + "tests": [ + { + "description": "0.0075 is multiple of 0.0001", + "data": 0.0075, + "valid": true + }, + { + "description": "0.00751 is not multiple of 0.0001", + "data": 0.00751, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/not.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/not.json new file mode 100644 index 0000000..cbb7f46 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/not.json @@ -0,0 +1,96 @@ +[ + { + "description": "not", + "schema": { + "not": {"type": "integer"} + }, + "tests": [ + { + "description": "allowed", + "data": "foo", + "valid": true + }, + { + "description": "disallowed", + "data": 1, + "valid": false + } + ] + }, + { + "description": "not multiple types", + "schema": { + "not": {"type": ["integer", "boolean"]} + }, + "tests": [ + { + "description": "valid", + "data": "foo", + "valid": true + }, + { + "description": "mismatch", + "data": 1, + "valid": false + }, + { + "description": "other mismatch", + "data": true, + "valid": false + } + ] + }, + { + "description": "not more complex schema", + "schema": { + "not": { + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "tests": [ + { + "description": "match", + "data": 1, + "valid": true + }, + { + "description": "other match", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "mismatch", + "data": {"foo": "bar"}, + "valid": false + } + ] + }, + { + "description": "forbidden property", + "schema": { + "properties": { + "foo": { + "not": {} + } + } + }, + "tests": [ + { + "description": "property present", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "property absent", + "data": {"bar": 1, "baz": 2}, + "valid": true + } + ] + } + +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/oneOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/oneOf.json new file mode 100644 index 0000000..3a03ded --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/oneOf.json @@ -0,0 +1,109 @@ +[ + { + "description": "oneOf", + "schema": { + "oneOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": 1, + "valid": true + }, + { + "description": "second oneOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both oneOf valid", + "data": 3, + "valid": false + }, + { + "description": "neither oneOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "oneOf with base schema", + "schema": { + "type": "string", + "oneOf" : [ + { + "minLength": 2 + }, + { + "maxLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one oneOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both oneOf valid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf complex types", + "schema": { + "oneOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second oneOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both oneOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": false + }, + { + "description": "neither oneOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/bignum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/bignum.json new file mode 100644 index 0000000..ccc7c17 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/bignum.json @@ -0,0 +1,107 @@ +[ + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": {"type": "string"}, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"maximum": 18446744073709551615}, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "maximum": 972783798187987123879878123.18878137, + "exclusiveMaximum": true + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"minimum": -18446744073709551615}, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "minimum": -972783798187987123879878123.18878137, + "exclusiveMinimum": true + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/ecmascript-regex.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/ecmascript-regex.json new file mode 100644 index 0000000..08dc936 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/ecmascript-regex.json @@ -0,0 +1,13 @@ +[ + { + "description": "ECMA 262 regex non-compliance", + "schema": { "format": "regex" }, + "tests": [ + { + "description": "ECMA 262 has no support for \\Z anchor from .NET", + "data": "^\\S(|(.|\\n)*\\S)\\Z", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/format.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/format.json new file mode 100644 index 0000000..32db8de --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/format.json @@ -0,0 +1,223 @@ +[ + { + "description": "validation of date-time strings", + "schema": {"format": "date-time"}, + "tests": [ + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + } + ] + }, + { + "description": "validation of URIs", + "schema": {"format": "uri"}, + "tests": [ + { + "description": "a valid URL with anchor tag", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid URL with anchor tag and parantheses", + "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", + "valid": true + }, + { + "description": "a valid URL with URL-encoded stuff", + "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid puny-coded URL ", + "data": "http://xn--nw2a.xn--j6w193g/", + "valid": true + }, + { + "description": "a valid URL with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid URL based on IPv4", + "data": "http://223.255.255.254", + "valid": true + }, + { + "description": "a valid URL with ftp scheme", + "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "valid": true + }, + { + "description": "a valid URL for a simple text file", + "data": "http://www.ietf.org/rfc/rfc2396.txt", + "valid": true + }, + { + "description": "a valid URL ", + "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", + "valid": true + }, + { + "description": "a valid mailto URI", + "data": "mailto:John.Doe@example.com", + "valid": true + }, + { + "description": "a valid newsgroup URI", + "data": "news:comp.infosystems.www.servers.unix", + "valid": true + }, + { + "description": "a valid tel URI", + "data": "tel:+1-816-555-1212", + "valid": true + }, + { + "description": "a valid URN", + "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", + "valid": true + }, + { + "description": "an invalid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": false + }, + { + "description": "an invalid relative URI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid URI", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "an invalid URI though valid URI reference", + "data": "abc", + "valid": false + }, + { + "description": "an invalid URI with spaces", + "data": "http:// shouldfail.com", + "valid": false + }, + { + "description": "an invalid URI with spaces and missing scheme", + "data": ":// should fail", + "valid": false + } + ] + }, + { + "description": "validation of e-mail addresses", + "schema": {"format": "email"}, + "tests": [ + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "valid": true + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "valid": false + } + ] + }, + { + "description": "validation of IP addresses", + "schema": {"format": "ipv4"}, + "tests": [ + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + } + ] + }, + { + "description": "validation of IPv6 addresses", + "schema": {"format": "ipv6"}, + "tests": [ + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": false + }, + { + "description": "an IPv6 address with too many components", + "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + } + ] + }, + { + "description": "validation of host names", + "schema": {"format": "hostname"}, + "tests": [ + { + "description": "a valid host name", + "data": "www.example.com", + "valid": true + }, + { + "description": "a host name starting with an illegal character", + "data": "-a-host-name-that-starts-with--", + "valid": false + }, + { + "description": "a host name containing illegal characters", + "data": "not_a_valid_host_name", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/zeroTerminatedFloats.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/zeroTerminatedFloats.json new file mode 100644 index 0000000..9b50ea2 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/optional/zeroTerminatedFloats.json @@ -0,0 +1,15 @@ +[ + { + "description": "some languages do not distinguish between different types of numeric value", + "schema": { + "type": "integer" + }, + "tests": [ + { + "description": "a float is not an integer even without fractional part", + "data": 1.0, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/pattern.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/pattern.json new file mode 100644 index 0000000..25e7299 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/pattern.json @@ -0,0 +1,34 @@ +[ + { + "description": "pattern validation", + "schema": {"pattern": "^a*$"}, + "tests": [ + { + "description": "a matching pattern is valid", + "data": "aaa", + "valid": true + }, + { + "description": "a non-matching pattern is invalid", + "data": "abc", + "valid": false + }, + { + "description": "ignores non-strings", + "data": true, + "valid": true + } + ] + }, + { + "description": "pattern is not anchored", + "schema": {"pattern": "a+"}, + "tests": [ + { + "description": "matches a substring", + "data": "xxaayy", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/patternProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/patternProperties.json new file mode 100644 index 0000000..5f741df --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/patternProperties.json @@ -0,0 +1,120 @@ +[ + { + "description": + "patternProperties validates properties matching a regex", + "schema": { + "patternProperties": { + "f.*o": {"type": "integer"} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "multiple valid matches is valid", + "data": {"foo": 1, "foooooo" : 2}, + "valid": true + }, + { + "description": "a single invalid match is invalid", + "data": {"foo": "bar", "fooooo": 2}, + "valid": false + }, + { + "description": "multiple invalid matches is invalid", + "data": {"foo": "bar", "foooooo" : "baz"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "multiple simultaneous patternProperties are validated", + "schema": { + "patternProperties": { + "a*": {"type": "integer"}, + "aaa*": {"maximum": 20} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"a": 21}, + "valid": true + }, + { + "description": "a simultaneous match is valid", + "data": {"aaaa": 18}, + "valid": true + }, + { + "description": "multiple matches is valid", + "data": {"a": 21, "aaaa": 18}, + "valid": true + }, + { + "description": "an invalid due to one is invalid", + "data": {"a": "bar"}, + "valid": false + }, + { + "description": "an invalid due to the other is invalid", + "data": {"aaaa": 31}, + "valid": false + }, + { + "description": "an invalid due to both is invalid", + "data": {"aaa": "foo", "aaaa": 31}, + "valid": false + } + ] + }, + { + "description": "regexes are not anchored by default and are case sensitive", + "schema": { + "patternProperties": { + "[0-9]{2,}": { "type": "boolean" }, + "X_": { "type": "string" } + } + }, + "tests": [ + { + "description": "non recognized members are ignored", + "data": { "answer 1": "42" }, + "valid": true + }, + { + "description": "recognized members are accounted for", + "data": { "a31b": null }, + "valid": false + }, + { + "description": "regexes are case sensitive", + "data": { "a_x_3": 3 }, + "valid": true + }, + { + "description": "regexes are case sensitive, 2", + "data": { "a_X_3": 3 }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/properties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/properties.json new file mode 100644 index 0000000..a830c67 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/properties.json @@ -0,0 +1,97 @@ +[ + { + "description": "object properties validation", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "string"} + } + }, + "tests": [ + { + "description": "both properties present and valid is valid", + "data": {"foo": 1, "bar": "baz"}, + "valid": true + }, + { + "description": "one property invalid is invalid", + "data": {"foo": 1, "bar": {}}, + "valid": false + }, + { + "description": "both properties invalid is invalid", + "data": {"foo": [], "bar": {}}, + "valid": false + }, + { + "description": "doesn't invalidate other properties", + "data": {"quux": []}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": + "properties, patternProperties, additionalProperties interaction", + "schema": { + "properties": { + "foo": {"type": "array", "maxItems": 3}, + "bar": {"type": "array"} + }, + "patternProperties": {"f.o": {"minItems": 2}}, + "additionalProperties": {"type": "integer"} + }, + "tests": [ + { + "description": "property validates property", + "data": {"foo": [1, 2]}, + "valid": true + }, + { + "description": "property invalidates property", + "data": {"foo": [1, 2, 3, 4]}, + "valid": false + }, + { + "description": "patternProperty invalidates property", + "data": {"foo": []}, + "valid": false + }, + { + "description": "patternProperty validates nonproperty", + "data": {"fxo": [1, 2]}, + "valid": true + }, + { + "description": "patternProperty invalidates nonproperty", + "data": {"fxo": []}, + "valid": false + }, + { + "description": "additionalProperty ignores property", + "data": {"bar": []}, + "valid": true + }, + { + "description": "additionalProperty validates others", + "data": {"quux": 3}, + "valid": true + }, + { + "description": "additionalProperty invalidates others", + "data": {"quux": "foo"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/ref.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/ref.json new file mode 100644 index 0000000..52cf50a --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/ref.json @@ -0,0 +1,300 @@ +[ + { + "description": "root pointer ref", + "schema": { + "properties": { + "foo": {"$ref": "#"} + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "match", + "data": {"foo": false}, + "valid": true + }, + { + "description": "recursive match", + "data": {"foo": {"foo": false}}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": false}, + "valid": false + }, + { + "description": "recursive mismatch", + "data": {"foo": {"bar": false}}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to object", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"$ref": "#/properties/foo"} + } + }, + "tests": [ + { + "description": "match", + "data": {"bar": 3}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": true}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to array", + "schema": { + "items": [ + {"type": "integer"}, + {"$ref": "#/items/0"} + ] + }, + "tests": [ + { + "description": "match array", + "data": [1, 2], + "valid": true + }, + { + "description": "mismatch array", + "data": [1, "foo"], + "valid": false + } + ] + }, + { + "description": "escaped pointer ref", + "schema": { + "tilda~field": {"type": "integer"}, + "slash/field": {"type": "integer"}, + "percent%field": {"type": "integer"}, + "properties": { + "tilda": {"$ref": "#/tilda~0field"}, + "slash": {"$ref": "#/slash~1field"}, + "percent": {"$ref": "#/percent%25field"} + } + }, + "tests": [ + { + "description": "slash invalid", + "data": {"slash": "aoeu"}, + "valid": false + }, + { + "description": "tilda invalid", + "data": {"tilda": "aoeu"}, + "valid": false + }, + { + "description": "percent invalid", + "data": {"percent": "aoeu"}, + "valid": false + }, + { + "description": "slash valid", + "data": {"slash": 123}, + "valid": true + }, + { + "description": "tilda valid", + "data": {"tilda": 123}, + "valid": true + }, + { + "description": "percent valid", + "data": {"percent": 123}, + "valid": true + } + ] + }, + { + "description": "nested refs", + "schema": { + "definitions": { + "a": {"type": "integer"}, + "b": {"$ref": "#/definitions/a"}, + "c": {"$ref": "#/definitions/b"} + }, + "$ref": "#/definitions/c" + }, + "tests": [ + { + "description": "nested ref valid", + "data": 5, + "valid": true + }, + { + "description": "nested ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref overrides any sibling keywords", + "schema": { + "definitions": { + "reffed": { + "type": "array" + } + }, + "properties": { + "foo": { + "$ref": "#/definitions/reffed", + "maxItems": 2 + } + } + }, + "tests": [ + { + "description": "ref valid", + "data": { "foo": [] }, + "valid": true + }, + { + "description": "ref valid, maxItems ignored", + "data": { "foo": [ 1, 2, 3] }, + "valid": true + }, + { + "description": "ref invalid", + "data": { "foo": "string" }, + "valid": false + } + ] + }, + { + "description": "remote ref, containing refs itself", + "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, + "tests": [ + { + "description": "remote ref valid", + "data": {"minLength": 1}, + "valid": true + }, + { + "description": "remote ref invalid", + "data": {"minLength": -1}, + "valid": false + } + ] + }, + { + "description": "property named $ref that is not a reference", + "schema": { + "properties": { + "$ref": {"type": "string"} + } + }, + "tests": [ + { + "description": "property named $ref valid", + "data": {"$ref": "a"}, + "valid": true + }, + { + "description": "property named $ref invalid", + "data": {"$ref": 2}, + "valid": false + } + ] + }, + { + "description": "Recursive references between schemas", + "schema": { + "id": "http://localhost:1234/tree", + "description": "tree of nodes", + "type": "object", + "properties": { + "meta": {"type": "string"}, + "nodes": { + "type": "array", + "items": {"$ref": "node"} + } + }, + "required": ["meta", "nodes"], + "definitions": { + "node": { + "id": "http://localhost:1234/node", + "description": "node", + "type": "object", + "properties": { + "value": {"type": "number"}, + "subtree": {"$ref": "tree"} + }, + "required": ["value"] + } + } + }, + "tests": [ + { + "description": "valid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 1.1}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": true + }, + { + "description": "invalid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": "string is invalid"}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/refRemote.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/refRemote.json new file mode 100644 index 0000000..8611fad --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/refRemote.json @@ -0,0 +1,171 @@ +[ + { + "description": "remote ref", + "schema": {"$ref": "http://localhost:1234/integer.json"}, + "tests": [ + { + "description": "remote ref valid", + "data": 1, + "valid": true + }, + { + "description": "remote ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "fragment within remote ref", + "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, + "tests": [ + { + "description": "remote fragment valid", + "data": 1, + "valid": true + }, + { + "description": "remote fragment invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref within remote ref", + "schema": { + "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" + }, + "tests": [ + { + "description": "ref within ref valid", + "data": 1, + "valid": true + }, + { + "description": "ref within ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "base URI change", + "schema": { + "id": "http://localhost:1234/", + "items": { + "id": "folder/", + "items": {"$ref": "folderInteger.json"} + } + }, + "tests": [ + { + "description": "base URI change ref valid", + "data": [[1]], + "valid": true + }, + { + "description": "base URI change ref invalid", + "data": [["a"]], + "valid": false + } + ] + }, + { + "description": "base URI change - change folder", + "schema": { + "id": "http://localhost:1234/scope_change_defs1.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz"} + }, + "definitions": { + "baz": { + "id": "folder/", + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "base URI change - change folder in subschema", + "schema": { + "id": "http://localhost:1234/scope_change_defs2.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz/definitions/bar"} + }, + "definitions": { + "baz": { + "id": "folder/", + "definitions": { + "bar": { + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "root ref in remote ref", + "schema": { + "id": "http://localhost:1234/object", + "type": "object", + "properties": { + "name": {"$ref": "name.json#/definitions/orNull"} + } + }, + "tests": [ + { + "description": "string is valid", + "data": { + "name": "foo" + }, + "valid": true + }, + { + "description": "null is valid", + "data": { + "name": null + }, + "valid": true + }, + { + "description": "object is invalid", + "data": { + "name": { + "name": null + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/required.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/required.json new file mode 100644 index 0000000..1e2a4f0 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/required.json @@ -0,0 +1,54 @@ +[ + { + "description": "required validation", + "schema": { + "properties": { + "foo": {}, + "bar": {} + }, + "required": ["foo"] + }, + "tests": [ + { + "description": "present required property is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "non-present required property is invalid", + "data": {"bar": 1}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "required default validation", + "schema": { + "properties": { + "foo": {} + } + }, + "tests": [ + { + "description": "not required by default", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/type.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/type.json new file mode 100644 index 0000000..6129374 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/type.json @@ -0,0 +1,345 @@ +[ + { + "description": "integer type matches integers", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "an integer is an integer", + "data": 1, + "valid": true + }, + { + "description": "a float is not an integer", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an integer", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not an integer, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not an integer", + "data": {}, + "valid": false + }, + { + "description": "an array is not an integer", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an integer", + "data": true, + "valid": false + }, + { + "description": "null is not an integer", + "data": null, + "valid": false + } + ] + }, + { + "description": "number type matches numbers", + "schema": {"type": "number"}, + "tests": [ + { + "description": "an integer is a number", + "data": 1, + "valid": true + }, + { + "description": "a float is a number", + "data": 1.1, + "valid": true + }, + { + "description": "a string is not a number", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not a number, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not a number", + "data": {}, + "valid": false + }, + { + "description": "an array is not a number", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a number", + "data": true, + "valid": false + }, + { + "description": "null is not a number", + "data": null, + "valid": false + } + ] + }, + { + "description": "string type matches strings", + "schema": {"type": "string"}, + "tests": [ + { + "description": "1 is not a string", + "data": 1, + "valid": false + }, + { + "description": "a float is not a string", + "data": 1.1, + "valid": false + }, + { + "description": "a string is a string", + "data": "foo", + "valid": true + }, + { + "description": "a string is still a string, even if it looks like a number", + "data": "1", + "valid": true + }, + { + "description": "an object is not a string", + "data": {}, + "valid": false + }, + { + "description": "an array is not a string", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a string", + "data": true, + "valid": false + }, + { + "description": "null is not a string", + "data": null, + "valid": false + } + ] + }, + { + "description": "object type matches objects", + "schema": {"type": "object"}, + "tests": [ + { + "description": "an integer is not an object", + "data": 1, + "valid": false + }, + { + "description": "a float is not an object", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an object", + "data": "foo", + "valid": false + }, + { + "description": "an object is an object", + "data": {}, + "valid": true + }, + { + "description": "an array is not an object", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an object", + "data": true, + "valid": false + }, + { + "description": "null is not an object", + "data": null, + "valid": false + } + ] + }, + { + "description": "array type matches arrays", + "schema": {"type": "array"}, + "tests": [ + { + "description": "an integer is not an array", + "data": 1, + "valid": false + }, + { + "description": "a float is not an array", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an array", + "data": "foo", + "valid": false + }, + { + "description": "an object is not an array", + "data": {}, + "valid": false + }, + { + "description": "an array is an array", + "data": [], + "valid": true + }, + { + "description": "a boolean is not an array", + "data": true, + "valid": false + }, + { + "description": "null is not an array", + "data": null, + "valid": false + } + ] + }, + { + "description": "boolean type matches booleans", + "schema": {"type": "boolean"}, + "tests": [ + { + "description": "an integer is not a boolean", + "data": 1, + "valid": false + }, + { + "description": "a float is not a boolean", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not a boolean", + "data": "foo", + "valid": false + }, + { + "description": "an object is not a boolean", + "data": {}, + "valid": false + }, + { + "description": "an array is not a boolean", + "data": [], + "valid": false + }, + { + "description": "a boolean is a boolean", + "data": true, + "valid": true + }, + { + "description": "null is not a boolean", + "data": null, + "valid": false + } + ] + }, + { + "description": "null type matches only the null object", + "schema": {"type": "null"}, + "tests": [ + { + "description": "an integer is not null", + "data": 1, + "valid": false + }, + { + "description": "a float is not null", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not null", + "data": "foo", + "valid": false + }, + { + "description": "an object is not null", + "data": {}, + "valid": false + }, + { + "description": "an array is not null", + "data": [], + "valid": false + }, + { + "description": "a boolean is not null", + "data": true, + "valid": false + }, + { + "description": "null is null", + "data": null, + "valid": true + } + ] + }, + { + "description": "multiple types can be specified in an array", + "schema": {"type": ["integer", "string"]}, + "tests": [ + { + "description": "an integer is valid", + "data": 1, + "valid": true + }, + { + "description": "a string is valid", + "data": "foo", + "valid": true + }, + { + "description": "a float is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "an object is invalid", + "data": {}, + "valid": false + }, + { + "description": "an array is invalid", + "data": [], + "valid": false + }, + { + "description": "a boolean is invalid", + "data": true, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/uniqueItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/uniqueItems.json new file mode 100644 index 0000000..c1f4ab9 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft4/uniqueItems.json @@ -0,0 +1,79 @@ +[ + { + "description": "uniqueItems validation", + "schema": {"uniqueItems": true}, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "non-unique array of integers is invalid", + "data": [1, 1], + "valid": false + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [1.0, 1.00, 1], + "valid": false + }, + { + "description": "unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "baz"}], + "valid": true + }, + { + "description": "non-unique array of objects is invalid", + "data": [{"foo": "bar"}, {"foo": "bar"}], + "valid": false + }, + { + "description": "unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : false}}} + ], + "valid": true + }, + { + "description": "non-unique array of nested objects is invalid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : true}}} + ], + "valid": false + }, + { + "description": "unique array of arrays is valid", + "data": [["foo"], ["bar"]], + "valid": true + }, + { + "description": "non-unique array of arrays is invalid", + "data": [["foo"], ["foo"]], + "valid": false + }, + { + "description": "1 and true are unique", + "data": [1, true], + "valid": true + }, + { + "description": "0 and false are unique", + "data": [0, false], + "valid": true + }, + { + "description": "unique heterogeneous types are valid", + "data": [{}, [1], true, null, 1], + "valid": true + }, + { + "description": "non-unique heterogeneous types are invalid", + "data": [{}, [1], true, null, {}, 1], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalItems.json new file mode 100644 index 0000000..abecc57 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalItems.json @@ -0,0 +1,87 @@ +[ + { + "description": "additionalItems as schema", + "schema": { + "items": [{}], + "additionalItems": {"type": "integer"} + }, + "tests": [ + { + "description": "additional items match schema", + "data": [ null, 2, 3, 4 ], + "valid": true + }, + { + "description": "additional items do not match schema", + "data": [ null, 2, 3, "foo" ], + "valid": false + } + ] + }, + { + "description": "items is schema, no additionalItems", + "schema": { + "items": {}, + "additionalItems": false + }, + "tests": [ + { + "description": "all items match schema", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + } + ] + }, + { + "description": "array of items with no additionalItems", + "schema": { + "items": [{}, {}, {}], + "additionalItems": false + }, + "tests": [ + { + "description": "fewer number of items present", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "equal number of items present", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "additional items are not permitted", + "data": [ 1, 2, 3, 4 ], + "valid": false + } + ] + }, + { + "description": "additionalItems as false without items", + "schema": {"additionalItems": false}, + "tests": [ + { + "description": + "items defaults to empty schema so everything is valid", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + } + ] + }, + { + "description": "additionalItems are allowed by default", + "schema": {"items": [{"type": "integer"}]}, + "tests": [ + { + "description": "only the first item is validated", + "data": [1, "foo", false], + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalProperties.json new file mode 100644 index 0000000..90d7607 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/additionalProperties.json @@ -0,0 +1,98 @@ +[ + { + "description": + "additionalProperties being false does not allow other properties", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "patternProperties": { "^v": {} }, + "additionalProperties": false + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobarbaz", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + }, + { + "description": "patternProperties are not additional properties", + "data": {"foo":1, "vroom": 2}, + "valid": true + } + ] + }, + { + "description": + "additionalProperties allows a schema which should validate", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional valid property is valid", + "data": {"foo" : 1, "bar" : 2, "quux" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : 12}, + "valid": false + } + ] + }, + { + "description": + "additionalProperties can exist by itself", + "schema": { + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "an additional valid property is valid", + "data": {"foo" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1}, + "valid": false + } + ] + }, + { + "description": "additionalProperties are allowed by default", + "schema": {"properties": {"foo": {}, "bar": {}}}, + "tests": [ + { + "description": "additional properties are allowed", + "data": {"foo": 1, "bar": 2, "quux": true}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/allOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/allOf.json new file mode 100644 index 0000000..00c016c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/allOf.json @@ -0,0 +1,145 @@ +[ + { + "description": "allOf", + "schema": { + "allOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "allOf", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "mismatch second", + "data": {"foo": "baz"}, + "valid": false + }, + { + "description": "mismatch first", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "wrong type", + "data": {"foo": "baz", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "allOf with base schema", + "schema": { + "properties": {"bar": {"type": "integer"}}, + "required": ["bar"], + "allOf" : [ + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + }, + { + "properties": { + "baz": {"type": "null"} + }, + "required": ["baz"] + } + ] + }, + "tests": [ + { + "description": "valid", + "data": {"foo": "quux", "bar": 2, "baz": null}, + "valid": true + }, + { + "description": "mismatch base schema", + "data": {"foo": "quux", "baz": null}, + "valid": false + }, + { + "description": "mismatch first allOf", + "data": {"bar": 2, "baz": null}, + "valid": false + }, + { + "description": "mismatch second allOf", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "mismatch both", + "data": {"bar": 2}, + "valid": false + } + ] + }, + { + "description": "allOf simple types", + "schema": { + "allOf": [ + {"maximum": 30}, + {"minimum": 20} + ] + }, + "tests": [ + { + "description": "valid", + "data": 25, + "valid": true + }, + { + "description": "mismatch one", + "data": 35, + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all true", + "schema": {"allOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "allOf with boolean schemas, some false", + "schema": {"allOf": [true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all false", + "schema": {"allOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/anyOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/anyOf.json new file mode 100644 index 0000000..4d05a9e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/anyOf.json @@ -0,0 +1,142 @@ +[ + { + "description": "anyOf", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first anyOf valid", + "data": 1, + "valid": true + }, + { + "description": "second anyOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both anyOf valid", + "data": 3, + "valid": true + }, + { + "description": "neither anyOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "anyOf with base schema", + "schema": { + "type": "string", + "anyOf" : [ + { + "maxLength": 2 + }, + { + "minLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one anyOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both anyOf invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf with boolean schemas, all true", + "schema": {"anyOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, some true", + "schema": {"anyOf": [true, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, all false", + "schema": {"anyOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf complex types", + "schema": { + "anyOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first anyOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second anyOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both anyOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "neither anyOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/boolean_schema.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/boolean_schema.json new file mode 100644 index 0000000..6d40f23 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/boolean_schema.json @@ -0,0 +1,104 @@ +[ + { + "description": "boolean schema 'true'", + "schema": true, + "tests": [ + { + "description": "number is valid", + "data": 1, + "valid": true + }, + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "boolean true is valid", + "data": true, + "valid": true + }, + { + "description": "boolean false is valid", + "data": false, + "valid": true + }, + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "object is valid", + "data": {"foo": "bar"}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + }, + { + "description": "array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "boolean schema 'false'", + "schema": false, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "valid": false + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + }, + { + "description": "boolean true is invalid", + "data": true, + "valid": false + }, + { + "description": "boolean false is invalid", + "data": false, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + }, + { + "description": "object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "empty object is invalid", + "data": {}, + "valid": false + }, + { + "description": "array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/const.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/const.json new file mode 100644 index 0000000..0fe00f2 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/const.json @@ -0,0 +1,86 @@ +[ + { + "description": "const validation", + "schema": {"const": 2}, + "tests": [ + { + "description": "same value is valid", + "data": 2, + "valid": true + }, + { + "description": "another value is invalid", + "data": 5, + "valid": false + }, + { + "description": "another type is invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "const with object", + "schema": {"const": {"foo": "bar", "baz": "bax"}}, + "tests": [ + { + "description": "same object is valid", + "data": {"foo": "bar", "baz": "bax"}, + "valid": true + }, + { + "description": "same object with different property order is valid", + "data": {"baz": "bax", "foo": "bar"}, + "valid": true + }, + { + "description": "another object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "another type is invalid", + "data": [1, 2], + "valid": false + } + ] + }, + { + "description": "const with array", + "schema": {"const": [{ "foo": "bar" }]}, + "tests": [ + { + "description": "same array is valid", + "data": [{"foo": "bar"}], + "valid": true + }, + { + "description": "another array item is invalid", + "data": [2], + "valid": false + }, + { + "description": "array with additional items is invalid", + "data": [1, 2, 3], + "valid": false + } + ] + }, + { + "description": "const with null", + "schema": {"const": null}, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "not null is invalid", + "data": 0, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/contains.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/contains.json new file mode 100644 index 0000000..b7ae5a2 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/contains.json @@ -0,0 +1,95 @@ +[ + { + "description": "contains keyword validation", + "schema": { + "contains": {"minimum": 5} + }, + "tests": [ + { + "description": "array with item matching schema (5) is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with item matching schema (6) is valid", + "data": [3, 4, 6], + "valid": true + }, + { + "description": "array with two items matching schema (5, 6) is valid", + "data": [3, 4, 5, 6], + "valid": true + }, + { + "description": "array without items matching schema is invalid", + "data": [2, 3, 4], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + }, + { + "description": "not array is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "contains keyword with const keyword", + "schema": { + "contains": { "const": 5 } + }, + "tests": [ + { + "description": "array with item 5 is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with two items 5 is valid", + "data": [3, 4, 5, 5], + "valid": true + }, + { + "description": "array without item 5 is invalid", + "data": [1, 2, 3, 4], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema true", + "schema": {"contains": true}, + "tests": [ + { + "description": "any non-empty array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema false", + "schema": {"contains": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/default.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/default.json new file mode 100644 index 0000000..1762977 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/default.json @@ -0,0 +1,49 @@ +[ + { + "description": "invalid type for default", + "schema": { + "properties": { + "foo": { + "type": "integer", + "default": [] + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"foo": 13}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + }, + { + "description": "invalid string value for default", + "schema": { + "properties": { + "bar": { + "type": "string", + "minLength": 4, + "default": "bad" + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"bar": "good"}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/definitions.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/definitions.json new file mode 100644 index 0000000..7f3b899 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/definitions.json @@ -0,0 +1,32 @@ +[ + { + "description": "valid definition", + "schema": {"$ref": "http://json-schema.org/draft-06/schema#"}, + "tests": [ + { + "description": "valid definition schema", + "data": { + "definitions": { + "foo": {"type": "integer"} + } + }, + "valid": true + } + ] + }, + { + "description": "invalid definition", + "schema": {"$ref": "http://json-schema.org/draft-06/schema#"}, + "tests": [ + { + "description": "invalid definition schema", + "data": { + "definitions": { + "foo": {"type": 1} + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/dependencies.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/dependencies.json new file mode 100644 index 0000000..80e552f --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/dependencies.json @@ -0,0 +1,172 @@ +[ + { + "description": "dependencies", + "schema": { + "dependencies": {"bar": ["foo"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependant", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "with dependency", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "dependencies with empty array", + "schema": { + "dependencies": {"bar": []} + }, + "tests": [ + { + "description": "empty object", + "data": {}, + "valid": true + }, + { + "description": "object with one property", + "data": {"bar": 2}, + "valid": true + } + ] + }, + { + "description": "multiple dependencies", + "schema": { + "dependencies": {"quux": ["foo", "bar"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependants", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "with dependencies", + "data": {"foo": 1, "bar": 2, "quux": 3}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"foo": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing other dependency", + "data": {"bar": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing both dependencies", + "data": {"quux": 1}, + "valid": false + } + ] + }, + { + "description": "multiple dependencies subschema", + "schema": { + "dependencies": { + "bar": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "integer"} + } + } + } + }, + "tests": [ + { + "description": "valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "no dependency", + "data": {"foo": "quux"}, + "valid": true + }, + { + "description": "wrong type", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "dependencies with boolean subschemas", + "schema": { + "dependencies": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "object with property having schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property having schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/enum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/enum.json new file mode 100644 index 0000000..f124436 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/enum.json @@ -0,0 +1,72 @@ +[ + { + "description": "simple enum validation", + "schema": {"enum": [1, 2, 3]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": 1, + "valid": true + }, + { + "description": "something else is invalid", + "data": 4, + "valid": false + } + ] + }, + { + "description": "heterogeneous enum validation", + "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": [], + "valid": true + }, + { + "description": "something else is invalid", + "data": null, + "valid": false + }, + { + "description": "objects are deep compared", + "data": {"foo": false}, + "valid": false + } + ] + }, + { + "description": "enums in properties", + "schema": { + "type":"object", + "properties": { + "foo": {"enum":["foo"]}, + "bar": {"enum":["bar"]} + }, + "required": ["bar"] + }, + "tests": [ + { + "description": "both properties are valid", + "data": {"foo":"foo", "bar":"bar"}, + "valid": true + }, + { + "description": "missing optional property is valid", + "data": {"bar":"bar"}, + "valid": true + }, + { + "description": "missing required property is invalid", + "data": {"foo":"foo"}, + "valid": false + }, + { + "description": "missing all properties is invalid", + "data": {}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMaximum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMaximum.json new file mode 100644 index 0000000..dc3cd70 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMaximum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMaximum validation", + "schema": { + "exclusiveMaximum": 3.0 + }, + "tests": [ + { + "description": "below the exclusiveMaximum is valid", + "data": 2.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 3.0, + "valid": false + }, + { + "description": "above the exclusiveMaximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMinimum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMinimum.json new file mode 100644 index 0000000..b38d7ec --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/exclusiveMinimum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMinimum validation", + "schema": { + "exclusiveMinimum": 1.1 + }, + "tests": [ + { + "description": "above the exclusiveMinimum is valid", + "data": 1.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "below the exclusiveMinimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/items.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/items.json new file mode 100644 index 0000000..13a6a11 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/items.json @@ -0,0 +1,133 @@ +[ + { + "description": "a schema given for items", + "schema": { + "items": {"type": "integer"} + }, + "tests": [ + { + "description": "valid items", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "wrong type of items", + "data": [1, "x"], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "length": 1 + }, + "valid": true + } + ] + }, + { + "description": "an array of schemas for items", + "schema": { + "items": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": false + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "items with boolean schema (true)", + "schema": {"items": true}, + "tests": [ + { + "description": "any array is valid", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schema (false)", + "schema": {"items": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": [ 1, "foo", true ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schemas", + "schema": { + "items": [true, false] + }, + "tests": [ + { + "description": "array with one item is valid", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with two items is invalid", + "data": [ 1, "foo" ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxItems.json new file mode 100644 index 0000000..3b53a6b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "maxItems validation", + "schema": {"maxItems": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": [1], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "too long is invalid", + "data": [1, 2, 3], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "foobar", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxLength.json new file mode 100644 index 0000000..811d35b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "maxLength validation", + "schema": {"maxLength": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too long is invalid", + "data": "foo", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + }, + { + "description": "two supplementary Unicode code points is long enough", + "data": "\uD83D\uDCA9\uD83D\uDCA9", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxProperties.json new file mode 100644 index 0000000..513731e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maxProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "maxProperties validation", + "schema": {"maxProperties": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "too long is invalid", + "data": {"foo": 1, "bar": 2, "baz": 3}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maximum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maximum.json new file mode 100644 index 0000000..8150984 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/maximum.json @@ -0,0 +1,28 @@ +[ + { + "description": "maximum validation", + "schema": {"maximum": 3.0}, + "tests": [ + { + "description": "below the maximum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 3.0, + "valid": true + }, + { + "description": "above the maximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minItems.json new file mode 100644 index 0000000..ed51188 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "minItems validation", + "schema": {"minItems": 1}, + "tests": [ + { + "description": "longer is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1], + "valid": true + }, + { + "description": "too short is invalid", + "data": [], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minLength.json new file mode 100644 index 0000000..3f09158 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "minLength validation", + "schema": {"minLength": 2}, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too short is invalid", + "data": "f", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 1, + "valid": true + }, + { + "description": "one supplementary Unicode code point is not long enough", + "data": "\uD83D\uDCA9", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minProperties.json new file mode 100644 index 0000000..49a0726 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "minProperties validation", + "schema": {"minProperties": 1}, + "tests": [ + { + "description": "longer is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "too short is invalid", + "data": {}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minimum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minimum.json new file mode 100644 index 0000000..bd1e95b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/minimum.json @@ -0,0 +1,28 @@ +[ + { + "description": "minimum validation", + "schema": {"minimum": 1.1}, + "tests": [ + { + "description": "above the minimum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 1.1, + "valid": true + }, + { + "description": "below the minimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/multipleOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/multipleOf.json new file mode 100644 index 0000000..ca3b761 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/multipleOf.json @@ -0,0 +1,60 @@ +[ + { + "description": "by int", + "schema": {"multipleOf": 2}, + "tests": [ + { + "description": "int by int", + "data": 10, + "valid": true + }, + { + "description": "int by int fail", + "data": 7, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "by number", + "schema": {"multipleOf": 1.5}, + "tests": [ + { + "description": "zero is multiple of anything", + "data": 0, + "valid": true + }, + { + "description": "4.5 is multiple of 1.5", + "data": 4.5, + "valid": true + }, + { + "description": "35 is not multiple of 1.5", + "data": 35, + "valid": false + } + ] + }, + { + "description": "by small number", + "schema": {"multipleOf": 0.0001}, + "tests": [ + { + "description": "0.0075 is multiple of 0.0001", + "data": 0.0075, + "valid": true + }, + { + "description": "0.00751 is not multiple of 0.0001", + "data": 0.00751, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/not.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/not.json new file mode 100644 index 0000000..98de0ed --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/not.json @@ -0,0 +1,117 @@ +[ + { + "description": "not", + "schema": { + "not": {"type": "integer"} + }, + "tests": [ + { + "description": "allowed", + "data": "foo", + "valid": true + }, + { + "description": "disallowed", + "data": 1, + "valid": false + } + ] + }, + { + "description": "not multiple types", + "schema": { + "not": {"type": ["integer", "boolean"]} + }, + "tests": [ + { + "description": "valid", + "data": "foo", + "valid": true + }, + { + "description": "mismatch", + "data": 1, + "valid": false + }, + { + "description": "other mismatch", + "data": true, + "valid": false + } + ] + }, + { + "description": "not more complex schema", + "schema": { + "not": { + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "tests": [ + { + "description": "match", + "data": 1, + "valid": true + }, + { + "description": "other match", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "mismatch", + "data": {"foo": "bar"}, + "valid": false + } + ] + }, + { + "description": "forbidden property", + "schema": { + "properties": { + "foo": { + "not": {} + } + } + }, + "tests": [ + { + "description": "property present", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "property absent", + "data": {"bar": 1, "baz": 2}, + "valid": true + } + ] + }, + { + "description": "not with boolean schema true", + "schema": {"not": true}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "not with boolean schema false", + "schema": {"not": false}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/oneOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/oneOf.json new file mode 100644 index 0000000..bc4295c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/oneOf.json @@ -0,0 +1,153 @@ +[ + { + "description": "oneOf", + "schema": { + "oneOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": 1, + "valid": true + }, + { + "description": "second oneOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both oneOf valid", + "data": 3, + "valid": false + }, + { + "description": "neither oneOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "oneOf with base schema", + "schema": { + "type": "string", + "oneOf" : [ + { + "minLength": 2 + }, + { + "maxLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one oneOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both oneOf valid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all true", + "schema": {"oneOf": [true, true, true]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, one true", + "schema": {"oneOf": [true, false, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "oneOf with boolean schemas, more than one true", + "schema": {"oneOf": [true, true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all false", + "schema": {"oneOf": [false, false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf complex types", + "schema": { + "oneOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second oneOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both oneOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": false + }, + { + "description": "neither oneOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/bignum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/bignum.json new file mode 100644 index 0000000..fac275e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/bignum.json @@ -0,0 +1,105 @@ +[ + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": {"type": "string"}, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"maximum": 18446744073709551615}, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "exclusiveMaximum": 972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"minimum": -18446744073709551615}, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "exclusiveMinimum": -972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/ecmascript-regex.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/ecmascript-regex.json new file mode 100644 index 0000000..08dc936 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/ecmascript-regex.json @@ -0,0 +1,13 @@ +[ + { + "description": "ECMA 262 regex non-compliance", + "schema": { "format": "regex" }, + "tests": [ + { + "description": "ECMA 262 has no support for \\Z anchor from .NET", + "data": "^\\S(|(.|\\n)*\\S)\\Z", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/format.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/format.json new file mode 100644 index 0000000..67f2fe6 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/format.json @@ -0,0 +1,458 @@ +[ + { + "description": "validation of date-time strings", + "schema": {"format": "date-time"}, + "tests": [ + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + } + ] + }, + { + "description": "validation of URIs", + "schema": {"format": "uri"}, + "tests": [ + { + "description": "a valid URL with anchor tag", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid URL with anchor tag and parantheses", + "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", + "valid": true + }, + { + "description": "a valid URL with URL-encoded stuff", + "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid puny-coded URL ", + "data": "http://xn--nw2a.xn--j6w193g/", + "valid": true + }, + { + "description": "a valid URL with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid URL based on IPv4", + "data": "http://223.255.255.254", + "valid": true + }, + { + "description": "a valid URL with ftp scheme", + "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "valid": true + }, + { + "description": "a valid URL for a simple text file", + "data": "http://www.ietf.org/rfc/rfc2396.txt", + "valid": true + }, + { + "description": "a valid URL ", + "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", + "valid": true + }, + { + "description": "a valid mailto URI", + "data": "mailto:John.Doe@example.com", + "valid": true + }, + { + "description": "a valid newsgroup URI", + "data": "news:comp.infosystems.www.servers.unix", + "valid": true + }, + { + "description": "a valid tel URI", + "data": "tel:+1-816-555-1212", + "valid": true + }, + { + "description": "a valid URN", + "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", + "valid": true + }, + { + "description": "an invalid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": false + }, + { + "description": "an invalid relative URI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid URI", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "an invalid URI though valid URI reference", + "data": "abc", + "valid": false + }, + { + "description": "an invalid URI with spaces", + "data": "http:// shouldfail.com", + "valid": false + }, + { + "description": "an invalid URI with spaces and missing scheme", + "data": ":// should fail", + "valid": false + } + ] + }, + { + "description": "validation of URI References", + "schema": {"format": "uri-reference"}, + "tests": [ + { + "description": "a valid URI", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid relative URI Reference", + "data": "/abc", + "valid": true + }, + { + "description": "an invalid URI Reference", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "a valid URI Reference", + "data": "abc", + "valid": true + }, + { + "description": "a valid URI fragment", + "data": "#fragment", + "valid": true + }, + { + "description": "an invalid URI fragment", + "data": "#frag\\ment", + "valid": false + } + ] + }, + { + "description": "format: uri-template", + "schema": { + "format": "uri-template" + }, + "tests": [ + { + "description": "a valid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term}", + "valid": true + }, + { + "description": "an invalid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term", + "valid": false + }, + { + "description": "a valid uri-template without variables", + "data": "http://example.com/dictionary", + "valid": true + }, + { + "description": "a valid relative uri-template", + "data": "dictionary/{term:1}/{term}", + "valid": true + } + ] + }, + { + "description": "validation of e-mail addresses", + "schema": {"format": "email"}, + "tests": [ + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "valid": true + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "valid": false + } + ] + }, + { + "description": "validation of IP addresses", + "schema": {"format": "ipv4"}, + "tests": [ + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + } + ] + }, + { + "description": "validation of IPv6 addresses", + "schema": {"format": "ipv6"}, + "tests": [ + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": false + }, + { + "description": "an IPv6 address with too many components", + "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + } + ] + }, + { + "description": "validation of host names", + "schema": {"format": "hostname"}, + "tests": [ + { + "description": "a valid host name", + "data": "www.example.com", + "valid": true + }, + { + "description": "a host name starting with an illegal character", + "data": "-a-host-name-that-starts-with--", + "valid": false + }, + { + "description": "a host name containing illegal characters", + "data": "not_a_valid_host_name", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", + "valid": false + } + ] + }, + { + "description": "validation of JSON-pointers (JSON String Representation)", + "schema": {"format": "json-pointer"}, + "tests": [ + { + "description": "a valid JSON-pointer", + "data": "/foo/bar~0/baz~1/%a", + "valid": true + }, + { + "description": "not a valid JSON-pointer (~ not escaped)", + "data": "/foo/bar~", + "valid": false + }, + { + "description": "valid JSON-pointer with empty segment", + "data": "/foo//bar", + "valid": true + }, + { + "description": "valid JSON-pointer with the last empty segment", + "data": "/foo/bar/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #1", + "data": "", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #2", + "data": "/foo", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #3", + "data": "/foo/0", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #4", + "data": "/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #5", + "data": "/a~1b", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #6", + "data": "/c%d", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #7", + "data": "/e^f", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #8", + "data": "/g|h", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #9", + "data": "/i\\j", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #10", + "data": "/k\"l", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #11", + "data": "/ ", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #12", + "data": "/m~0n", + "valid": true + }, + { + "description": "valid JSON-pointer used adding to the last array position", + "data": "/foo/-", + "valid": true + }, + { + "description": "valid JSON-pointer (- used as object member name)", + "data": "/foo/-/bar", + "valid": true + }, + { + "description": "valid JSON-pointer (multiple escaped characters)", + "data": "/~1~0~0~1~1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #1", + "data": "/~1.1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #2", + "data": "/~0.1", + "valid": true + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", + "data": "#", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", + "data": "#/", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", + "data": "#a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #1", + "data": "/~0~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #2", + "data": "/~0/~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #1", + "data": "/~2", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #2", + "data": "/~-1", + "valid": false + }, + { + "description": "not a valid JSON-pointer (multiple characters not escaped)", + "data": "/~~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", + "data": "a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", + "data": "0", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3", + "data": "a/a", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/zeroTerminatedFloats.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/zeroTerminatedFloats.json new file mode 100644 index 0000000..1bcdf96 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/optional/zeroTerminatedFloats.json @@ -0,0 +1,15 @@ +[ + { + "description": "some languages do not distinguish between different types of numeric value", + "schema": { + "type": "integer" + }, + "tests": [ + { + "description": "a float without fractional part is an integer", + "data": 1.0, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/pattern.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/pattern.json new file mode 100644 index 0000000..25e7299 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/pattern.json @@ -0,0 +1,34 @@ +[ + { + "description": "pattern validation", + "schema": {"pattern": "^a*$"}, + "tests": [ + { + "description": "a matching pattern is valid", + "data": "aaa", + "valid": true + }, + { + "description": "a non-matching pattern is invalid", + "data": "abc", + "valid": false + }, + { + "description": "ignores non-strings", + "data": true, + "valid": true + } + ] + }, + { + "description": "pattern is not anchored", + "schema": {"pattern": "a+"}, + "tests": [ + { + "description": "matches a substring", + "data": "xxaayy", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/patternProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/patternProperties.json new file mode 100644 index 0000000..1d04a16 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/patternProperties.json @@ -0,0 +1,151 @@ +[ + { + "description": + "patternProperties validates properties matching a regex", + "schema": { + "patternProperties": { + "f.*o": {"type": "integer"} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "multiple valid matches is valid", + "data": {"foo": 1, "foooooo" : 2}, + "valid": true + }, + { + "description": "a single invalid match is invalid", + "data": {"foo": "bar", "fooooo": 2}, + "valid": false + }, + { + "description": "multiple invalid matches is invalid", + "data": {"foo": "bar", "foooooo" : "baz"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["foo"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foo", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "multiple simultaneous patternProperties are validated", + "schema": { + "patternProperties": { + "a*": {"type": "integer"}, + "aaa*": {"maximum": 20} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"a": 21}, + "valid": true + }, + { + "description": "a simultaneous match is valid", + "data": {"aaaa": 18}, + "valid": true + }, + { + "description": "multiple matches is valid", + "data": {"a": 21, "aaaa": 18}, + "valid": true + }, + { + "description": "an invalid due to one is invalid", + "data": {"a": "bar"}, + "valid": false + }, + { + "description": "an invalid due to the other is invalid", + "data": {"aaaa": 31}, + "valid": false + }, + { + "description": "an invalid due to both is invalid", + "data": {"aaa": "foo", "aaaa": 31}, + "valid": false + } + ] + }, + { + "description": "regexes are not anchored by default and are case sensitive", + "schema": { + "patternProperties": { + "[0-9]{2,}": { "type": "boolean" }, + "X_": { "type": "string" } + } + }, + "tests": [ + { + "description": "non recognized members are ignored", + "data": { "answer 1": "42" }, + "valid": true + }, + { + "description": "recognized members are accounted for", + "data": { "a31b": null }, + "valid": false + }, + { + "description": "regexes are case sensitive", + "data": { "a_x_3": 3 }, + "valid": true + }, + { + "description": "regexes are case sensitive, 2", + "data": { "a_X_3": 3 }, + "valid": false + } + ] + }, + { + "description": "patternProperties with boolean schemas", + "schema": { + "patternProperties": { + "f.*": true, + "b.*": false + } + }, + "tests": [ + { + "description": "object with property matching schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property matching schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/properties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/properties.json new file mode 100644 index 0000000..c8ad719 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/properties.json @@ -0,0 +1,128 @@ +[ + { + "description": "object properties validation", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "string"} + } + }, + "tests": [ + { + "description": "both properties present and valid is valid", + "data": {"foo": 1, "bar": "baz"}, + "valid": true + }, + { + "description": "one property invalid is invalid", + "data": {"foo": 1, "bar": {}}, + "valid": false + }, + { + "description": "both properties invalid is invalid", + "data": {"foo": [], "bar": {}}, + "valid": false + }, + { + "description": "doesn't invalidate other properties", + "data": {"quux": []}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": + "properties, patternProperties, additionalProperties interaction", + "schema": { + "properties": { + "foo": {"type": "array", "maxItems": 3}, + "bar": {"type": "array"} + }, + "patternProperties": {"f.o": {"minItems": 2}}, + "additionalProperties": {"type": "integer"} + }, + "tests": [ + { + "description": "property validates property", + "data": {"foo": [1, 2]}, + "valid": true + }, + { + "description": "property invalidates property", + "data": {"foo": [1, 2, 3, 4]}, + "valid": false + }, + { + "description": "patternProperty invalidates property", + "data": {"foo": []}, + "valid": false + }, + { + "description": "patternProperty validates nonproperty", + "data": {"fxo": [1, 2]}, + "valid": true + }, + { + "description": "patternProperty invalidates nonproperty", + "data": {"fxo": []}, + "valid": false + }, + { + "description": "additionalProperty ignores property", + "data": {"bar": []}, + "valid": true + }, + { + "description": "additionalProperty validates others", + "data": {"quux": 3}, + "valid": true + }, + { + "description": "additionalProperty invalidates others", + "data": {"quux": "foo"}, + "valid": false + } + ] + }, + { + "description": "properties with boolean schema", + "schema": { + "properties": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "no property present is valid", + "data": {}, + "valid": true + }, + { + "description": "only 'true' property present is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "only 'false' property present is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "both properties present is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/propertyNames.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/propertyNames.json new file mode 100644 index 0000000..8423690 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/propertyNames.json @@ -0,0 +1,78 @@ +[ + { + "description": "propertyNames validation", + "schema": { + "propertyNames": {"maxLength": 3} + }, + "tests": [ + { + "description": "all property names valid", + "data": { + "f": {}, + "foo": {} + }, + "valid": true + }, + { + "description": "some property names invalid", + "data": { + "foo": {}, + "foobar": {} + }, + "valid": false + }, + { + "description": "object without properties is valid", + "data": {}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [1, 2, 3, 4], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema true", + "schema": {"propertyNames": true}, + "tests": [ + { + "description": "object with any properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema false", + "schema": {"propertyNames": false}, + "tests": [ + { + "description": "object with any properties is invalid", + "data": {"foo": 1}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/ref.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/ref.json new file mode 100644 index 0000000..5b58964 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/ref.json @@ -0,0 +1,332 @@ +[ + { + "description": "root pointer ref", + "schema": { + "properties": { + "foo": {"$ref": "#"} + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "match", + "data": {"foo": false}, + "valid": true + }, + { + "description": "recursive match", + "data": {"foo": {"foo": false}}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": false}, + "valid": false + }, + { + "description": "recursive mismatch", + "data": {"foo": {"bar": false}}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to object", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"$ref": "#/properties/foo"} + } + }, + "tests": [ + { + "description": "match", + "data": {"bar": 3}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": true}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to array", + "schema": { + "items": [ + {"type": "integer"}, + {"$ref": "#/items/0"} + ] + }, + "tests": [ + { + "description": "match array", + "data": [1, 2], + "valid": true + }, + { + "description": "mismatch array", + "data": [1, "foo"], + "valid": false + } + ] + }, + { + "description": "escaped pointer ref", + "schema": { + "tilda~field": {"type": "integer"}, + "slash/field": {"type": "integer"}, + "percent%field": {"type": "integer"}, + "properties": { + "tilda": {"$ref": "#/tilda~0field"}, + "slash": {"$ref": "#/slash~1field"}, + "percent": {"$ref": "#/percent%25field"} + } + }, + "tests": [ + { + "description": "slash invalid", + "data": {"slash": "aoeu"}, + "valid": false + }, + { + "description": "tilda invalid", + "data": {"tilda": "aoeu"}, + "valid": false + }, + { + "description": "percent invalid", + "data": {"percent": "aoeu"}, + "valid": false + }, + { + "description": "slash valid", + "data": {"slash": 123}, + "valid": true + }, + { + "description": "tilda valid", + "data": {"tilda": 123}, + "valid": true + }, + { + "description": "percent valid", + "data": {"percent": 123}, + "valid": true + } + ] + }, + { + "description": "nested refs", + "schema": { + "definitions": { + "a": {"type": "integer"}, + "b": {"$ref": "#/definitions/a"}, + "c": {"$ref": "#/definitions/b"} + }, + "$ref": "#/definitions/c" + }, + "tests": [ + { + "description": "nested ref valid", + "data": 5, + "valid": true + }, + { + "description": "nested ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref overrides any sibling keywords", + "schema": { + "definitions": { + "reffed": { + "type": "array" + } + }, + "properties": { + "foo": { + "$ref": "#/definitions/reffed", + "maxItems": 2 + } + } + }, + "tests": [ + { + "description": "ref valid", + "data": { "foo": [] }, + "valid": true + }, + { + "description": "ref valid, maxItems ignored", + "data": { "foo": [ 1, 2, 3] }, + "valid": true + }, + { + "description": "ref invalid", + "data": { "foo": "string" }, + "valid": false + } + ] + }, + { + "description": "remote ref, containing refs itself", + "schema": {"$ref": "http://json-schema.org/draft-06/schema#"}, + "tests": [ + { + "description": "remote ref valid", + "data": {"minLength": 1}, + "valid": true + }, + { + "description": "remote ref invalid", + "data": {"minLength": -1}, + "valid": false + } + ] + }, + { + "description": "property named $ref that is not a reference", + "schema": { + "properties": { + "$ref": {"type": "string"} + } + }, + "tests": [ + { + "description": "property named $ref valid", + "data": {"$ref": "a"}, + "valid": true + }, + { + "description": "property named $ref invalid", + "data": {"$ref": 2}, + "valid": false + } + ] + }, + { + "description": "$ref to boolean schema true", + "schema": { + "$ref": "#/definitions/bool", + "definitions": { + "bool": true + } + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "$ref to boolean schema false", + "schema": { + "$ref": "#/definitions/bool", + "definitions": { + "bool": false + } + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "Recursive references between schemas", + "schema": { + "$id": "http://localhost:1234/tree", + "description": "tree of nodes", + "type": "object", + "properties": { + "meta": {"type": "string"}, + "nodes": { + "type": "array", + "items": {"$ref": "node"} + } + }, + "required": ["meta", "nodes"], + "definitions": { + "node": { + "$id": "http://localhost:1234/node", + "description": "node", + "type": "object", + "properties": { + "value": {"type": "number"}, + "subtree": {"$ref": "tree"} + }, + "required": ["value"] + } + } + }, + "tests": [ + { + "description": "valid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 1.1}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": true + }, + { + "description": "invalid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": "string is invalid"}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/refRemote.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/refRemote.json new file mode 100644 index 0000000..819d326 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/refRemote.json @@ -0,0 +1,171 @@ +[ + { + "description": "remote ref", + "schema": {"$ref": "http://localhost:1234/integer.json"}, + "tests": [ + { + "description": "remote ref valid", + "data": 1, + "valid": true + }, + { + "description": "remote ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "fragment within remote ref", + "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, + "tests": [ + { + "description": "remote fragment valid", + "data": 1, + "valid": true + }, + { + "description": "remote fragment invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref within remote ref", + "schema": { + "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" + }, + "tests": [ + { + "description": "ref within ref valid", + "data": 1, + "valid": true + }, + { + "description": "ref within ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "base URI change", + "schema": { + "$id": "http://localhost:1234/", + "items": { + "$id": "folder/", + "items": {"$ref": "folderInteger.json"} + } + }, + "tests": [ + { + "description": "base URI change ref valid", + "data": [[1]], + "valid": true + }, + { + "description": "base URI change ref invalid", + "data": [["a"]], + "valid": false + } + ] + }, + { + "description": "base URI change - change folder", + "schema": { + "$id": "http://localhost:1234/scope_change_defs1.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz"} + }, + "definitions": { + "baz": { + "$id": "folder/", + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "base URI change - change folder in subschema", + "schema": { + "$id": "http://localhost:1234/scope_change_defs2.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz/definitions/bar"} + }, + "definitions": { + "baz": { + "$id": "folder/", + "definitions": { + "bar": { + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "root ref in remote ref", + "schema": { + "$id": "http://localhost:1234/object", + "type": "object", + "properties": { + "name": {"$ref": "name.json#/definitions/orNull"} + } + }, + "tests": [ + { + "description": "string is valid", + "data": { + "name": "foo" + }, + "valid": true + }, + { + "description": "null is valid", + "data": { + "name": null + }, + "valid": true + }, + { + "description": "object is invalid", + "data": { + "name": { + "name": null + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/required.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/required.json new file mode 100644 index 0000000..bd96907 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/required.json @@ -0,0 +1,70 @@ +[ + { + "description": "required validation", + "schema": { + "properties": { + "foo": {}, + "bar": {} + }, + "required": ["foo"] + }, + "tests": [ + { + "description": "present required property is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "non-present required property is invalid", + "data": {"bar": 1}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "required default validation", + "schema": { + "properties": { + "foo": {} + } + }, + "tests": [ + { + "description": "not required by default", + "data": {}, + "valid": true + } + ] + }, + { + "description": "required with empty array", + "schema": { + "properties": { + "foo": {} + }, + "required": [] + }, + "tests": [ + { + "description": "property not required", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/type.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/type.json new file mode 100644 index 0000000..6129374 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/type.json @@ -0,0 +1,345 @@ +[ + { + "description": "integer type matches integers", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "an integer is an integer", + "data": 1, + "valid": true + }, + { + "description": "a float is not an integer", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an integer", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not an integer, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not an integer", + "data": {}, + "valid": false + }, + { + "description": "an array is not an integer", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an integer", + "data": true, + "valid": false + }, + { + "description": "null is not an integer", + "data": null, + "valid": false + } + ] + }, + { + "description": "number type matches numbers", + "schema": {"type": "number"}, + "tests": [ + { + "description": "an integer is a number", + "data": 1, + "valid": true + }, + { + "description": "a float is a number", + "data": 1.1, + "valid": true + }, + { + "description": "a string is not a number", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not a number, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not a number", + "data": {}, + "valid": false + }, + { + "description": "an array is not a number", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a number", + "data": true, + "valid": false + }, + { + "description": "null is not a number", + "data": null, + "valid": false + } + ] + }, + { + "description": "string type matches strings", + "schema": {"type": "string"}, + "tests": [ + { + "description": "1 is not a string", + "data": 1, + "valid": false + }, + { + "description": "a float is not a string", + "data": 1.1, + "valid": false + }, + { + "description": "a string is a string", + "data": "foo", + "valid": true + }, + { + "description": "a string is still a string, even if it looks like a number", + "data": "1", + "valid": true + }, + { + "description": "an object is not a string", + "data": {}, + "valid": false + }, + { + "description": "an array is not a string", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a string", + "data": true, + "valid": false + }, + { + "description": "null is not a string", + "data": null, + "valid": false + } + ] + }, + { + "description": "object type matches objects", + "schema": {"type": "object"}, + "tests": [ + { + "description": "an integer is not an object", + "data": 1, + "valid": false + }, + { + "description": "a float is not an object", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an object", + "data": "foo", + "valid": false + }, + { + "description": "an object is an object", + "data": {}, + "valid": true + }, + { + "description": "an array is not an object", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an object", + "data": true, + "valid": false + }, + { + "description": "null is not an object", + "data": null, + "valid": false + } + ] + }, + { + "description": "array type matches arrays", + "schema": {"type": "array"}, + "tests": [ + { + "description": "an integer is not an array", + "data": 1, + "valid": false + }, + { + "description": "a float is not an array", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an array", + "data": "foo", + "valid": false + }, + { + "description": "an object is not an array", + "data": {}, + "valid": false + }, + { + "description": "an array is an array", + "data": [], + "valid": true + }, + { + "description": "a boolean is not an array", + "data": true, + "valid": false + }, + { + "description": "null is not an array", + "data": null, + "valid": false + } + ] + }, + { + "description": "boolean type matches booleans", + "schema": {"type": "boolean"}, + "tests": [ + { + "description": "an integer is not a boolean", + "data": 1, + "valid": false + }, + { + "description": "a float is not a boolean", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not a boolean", + "data": "foo", + "valid": false + }, + { + "description": "an object is not a boolean", + "data": {}, + "valid": false + }, + { + "description": "an array is not a boolean", + "data": [], + "valid": false + }, + { + "description": "a boolean is a boolean", + "data": true, + "valid": true + }, + { + "description": "null is not a boolean", + "data": null, + "valid": false + } + ] + }, + { + "description": "null type matches only the null object", + "schema": {"type": "null"}, + "tests": [ + { + "description": "an integer is not null", + "data": 1, + "valid": false + }, + { + "description": "a float is not null", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not null", + "data": "foo", + "valid": false + }, + { + "description": "an object is not null", + "data": {}, + "valid": false + }, + { + "description": "an array is not null", + "data": [], + "valid": false + }, + { + "description": "a boolean is not null", + "data": true, + "valid": false + }, + { + "description": "null is null", + "data": null, + "valid": true + } + ] + }, + { + "description": "multiple types can be specified in an array", + "schema": {"type": ["integer", "string"]}, + "tests": [ + { + "description": "an integer is valid", + "data": 1, + "valid": true + }, + { + "description": "a string is valid", + "data": "foo", + "valid": true + }, + { + "description": "a float is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "an object is invalid", + "data": {}, + "valid": false + }, + { + "description": "an array is invalid", + "data": [], + "valid": false + }, + { + "description": "a boolean is invalid", + "data": true, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/uniqueItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/uniqueItems.json new file mode 100644 index 0000000..c1f4ab9 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft6/uniqueItems.json @@ -0,0 +1,79 @@ +[ + { + "description": "uniqueItems validation", + "schema": {"uniqueItems": true}, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "non-unique array of integers is invalid", + "data": [1, 1], + "valid": false + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [1.0, 1.00, 1], + "valid": false + }, + { + "description": "unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "baz"}], + "valid": true + }, + { + "description": "non-unique array of objects is invalid", + "data": [{"foo": "bar"}, {"foo": "bar"}], + "valid": false + }, + { + "description": "unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : false}}} + ], + "valid": true + }, + { + "description": "non-unique array of nested objects is invalid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : true}}} + ], + "valid": false + }, + { + "description": "unique array of arrays is valid", + "data": [["foo"], ["bar"]], + "valid": true + }, + { + "description": "non-unique array of arrays is invalid", + "data": [["foo"], ["foo"]], + "valid": false + }, + { + "description": "1 and true are unique", + "data": [1, true], + "valid": true + }, + { + "description": "0 and false are unique", + "data": [0, false], + "valid": true + }, + { + "description": "unique heterogeneous types are valid", + "data": [{}, [1], true, null, 1], + "valid": true + }, + { + "description": "non-unique heterogeneous types are invalid", + "data": [{}, [1], true, null, {}, 1], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalItems.json new file mode 100644 index 0000000..abecc57 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalItems.json @@ -0,0 +1,87 @@ +[ + { + "description": "additionalItems as schema", + "schema": { + "items": [{}], + "additionalItems": {"type": "integer"} + }, + "tests": [ + { + "description": "additional items match schema", + "data": [ null, 2, 3, 4 ], + "valid": true + }, + { + "description": "additional items do not match schema", + "data": [ null, 2, 3, "foo" ], + "valid": false + } + ] + }, + { + "description": "items is schema, no additionalItems", + "schema": { + "items": {}, + "additionalItems": false + }, + "tests": [ + { + "description": "all items match schema", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + } + ] + }, + { + "description": "array of items with no additionalItems", + "schema": { + "items": [{}, {}, {}], + "additionalItems": false + }, + "tests": [ + { + "description": "fewer number of items present", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "equal number of items present", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "additional items are not permitted", + "data": [ 1, 2, 3, 4 ], + "valid": false + } + ] + }, + { + "description": "additionalItems as false without items", + "schema": {"additionalItems": false}, + "tests": [ + { + "description": + "items defaults to empty schema so everything is valid", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + } + ] + }, + { + "description": "additionalItems are allowed by default", + "schema": {"items": [{"type": "integer"}]}, + "tests": [ + { + "description": "only the first item is validated", + "data": [1, "foo", false], + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalProperties.json new file mode 100644 index 0000000..90d7607 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/additionalProperties.json @@ -0,0 +1,98 @@ +[ + { + "description": + "additionalProperties being false does not allow other properties", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "patternProperties": { "^v": {} }, + "additionalProperties": false + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobarbaz", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + }, + { + "description": "patternProperties are not additional properties", + "data": {"foo":1, "vroom": 2}, + "valid": true + } + ] + }, + { + "description": + "additionalProperties allows a schema which should validate", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional valid property is valid", + "data": {"foo" : 1, "bar" : 2, "quux" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : 12}, + "valid": false + } + ] + }, + { + "description": + "additionalProperties can exist by itself", + "schema": { + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "an additional valid property is valid", + "data": {"foo" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1}, + "valid": false + } + ] + }, + { + "description": "additionalProperties are allowed by default", + "schema": {"properties": {"foo": {}, "bar": {}}}, + "tests": [ + { + "description": "additional properties are allowed", + "data": {"foo": 1, "bar": 2, "quux": true}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/allOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/allOf.json new file mode 100644 index 0000000..00c016c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/allOf.json @@ -0,0 +1,145 @@ +[ + { + "description": "allOf", + "schema": { + "allOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "allOf", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "mismatch second", + "data": {"foo": "baz"}, + "valid": false + }, + { + "description": "mismatch first", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "wrong type", + "data": {"foo": "baz", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "allOf with base schema", + "schema": { + "properties": {"bar": {"type": "integer"}}, + "required": ["bar"], + "allOf" : [ + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + }, + { + "properties": { + "baz": {"type": "null"} + }, + "required": ["baz"] + } + ] + }, + "tests": [ + { + "description": "valid", + "data": {"foo": "quux", "bar": 2, "baz": null}, + "valid": true + }, + { + "description": "mismatch base schema", + "data": {"foo": "quux", "baz": null}, + "valid": false + }, + { + "description": "mismatch first allOf", + "data": {"bar": 2, "baz": null}, + "valid": false + }, + { + "description": "mismatch second allOf", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "mismatch both", + "data": {"bar": 2}, + "valid": false + } + ] + }, + { + "description": "allOf simple types", + "schema": { + "allOf": [ + {"maximum": 30}, + {"minimum": 20} + ] + }, + "tests": [ + { + "description": "valid", + "data": 25, + "valid": true + }, + { + "description": "mismatch one", + "data": 35, + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all true", + "schema": {"allOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "allOf with boolean schemas, some false", + "schema": {"allOf": [true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all false", + "schema": {"allOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/anyOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/anyOf.json new file mode 100644 index 0000000..4d05a9e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/anyOf.json @@ -0,0 +1,142 @@ +[ + { + "description": "anyOf", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first anyOf valid", + "data": 1, + "valid": true + }, + { + "description": "second anyOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both anyOf valid", + "data": 3, + "valid": true + }, + { + "description": "neither anyOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "anyOf with base schema", + "schema": { + "type": "string", + "anyOf" : [ + { + "maxLength": 2 + }, + { + "minLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one anyOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both anyOf invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf with boolean schemas, all true", + "schema": {"anyOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, some true", + "schema": {"anyOf": [true, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, all false", + "schema": {"anyOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf complex types", + "schema": { + "anyOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first anyOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second anyOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both anyOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "neither anyOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/boolean_schema.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/boolean_schema.json new file mode 100644 index 0000000..6d40f23 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/boolean_schema.json @@ -0,0 +1,104 @@ +[ + { + "description": "boolean schema 'true'", + "schema": true, + "tests": [ + { + "description": "number is valid", + "data": 1, + "valid": true + }, + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "boolean true is valid", + "data": true, + "valid": true + }, + { + "description": "boolean false is valid", + "data": false, + "valid": true + }, + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "object is valid", + "data": {"foo": "bar"}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + }, + { + "description": "array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "boolean schema 'false'", + "schema": false, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "valid": false + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + }, + { + "description": "boolean true is invalid", + "data": true, + "valid": false + }, + { + "description": "boolean false is invalid", + "data": false, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + }, + { + "description": "object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "empty object is invalid", + "data": {}, + "valid": false + }, + { + "description": "array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/const.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/const.json new file mode 100644 index 0000000..0fe00f2 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/const.json @@ -0,0 +1,86 @@ +[ + { + "description": "const validation", + "schema": {"const": 2}, + "tests": [ + { + "description": "same value is valid", + "data": 2, + "valid": true + }, + { + "description": "another value is invalid", + "data": 5, + "valid": false + }, + { + "description": "another type is invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "const with object", + "schema": {"const": {"foo": "bar", "baz": "bax"}}, + "tests": [ + { + "description": "same object is valid", + "data": {"foo": "bar", "baz": "bax"}, + "valid": true + }, + { + "description": "same object with different property order is valid", + "data": {"baz": "bax", "foo": "bar"}, + "valid": true + }, + { + "description": "another object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "another type is invalid", + "data": [1, 2], + "valid": false + } + ] + }, + { + "description": "const with array", + "schema": {"const": [{ "foo": "bar" }]}, + "tests": [ + { + "description": "same array is valid", + "data": [{"foo": "bar"}], + "valid": true + }, + { + "description": "another array item is invalid", + "data": [2], + "valid": false + }, + { + "description": "array with additional items is invalid", + "data": [1, 2, 3], + "valid": false + } + ] + }, + { + "description": "const with null", + "schema": {"const": null}, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "not null is invalid", + "data": 0, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/contains.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/contains.json new file mode 100644 index 0000000..b7ae5a2 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/contains.json @@ -0,0 +1,95 @@ +[ + { + "description": "contains keyword validation", + "schema": { + "contains": {"minimum": 5} + }, + "tests": [ + { + "description": "array with item matching schema (5) is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with item matching schema (6) is valid", + "data": [3, 4, 6], + "valid": true + }, + { + "description": "array with two items matching schema (5, 6) is valid", + "data": [3, 4, 5, 6], + "valid": true + }, + { + "description": "array without items matching schema is invalid", + "data": [2, 3, 4], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + }, + { + "description": "not array is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "contains keyword with const keyword", + "schema": { + "contains": { "const": 5 } + }, + "tests": [ + { + "description": "array with item 5 is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with two items 5 is valid", + "data": [3, 4, 5, 5], + "valid": true + }, + { + "description": "array without item 5 is invalid", + "data": [1, 2, 3, 4], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema true", + "schema": {"contains": true}, + "tests": [ + { + "description": "any non-empty array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema false", + "schema": {"contains": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/default.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/default.json new file mode 100644 index 0000000..1762977 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/default.json @@ -0,0 +1,49 @@ +[ + { + "description": "invalid type for default", + "schema": { + "properties": { + "foo": { + "type": "integer", + "default": [] + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"foo": 13}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + }, + { + "description": "invalid string value for default", + "schema": { + "properties": { + "bar": { + "type": "string", + "minLength": 4, + "default": "bad" + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"bar": "good"}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/definitions.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/definitions.json new file mode 100644 index 0000000..4360406 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/definitions.json @@ -0,0 +1,32 @@ +[ + { + "description": "valid definition", + "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, + "tests": [ + { + "description": "valid definition schema", + "data": { + "definitions": { + "foo": {"type": "integer"} + } + }, + "valid": true + } + ] + }, + { + "description": "invalid definition", + "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, + "tests": [ + { + "description": "invalid definition schema", + "data": { + "definitions": { + "foo": {"type": 1} + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/dependencies.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/dependencies.json new file mode 100644 index 0000000..80e552f --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/dependencies.json @@ -0,0 +1,172 @@ +[ + { + "description": "dependencies", + "schema": { + "dependencies": {"bar": ["foo"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependant", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "with dependency", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "dependencies with empty array", + "schema": { + "dependencies": {"bar": []} + }, + "tests": [ + { + "description": "empty object", + "data": {}, + "valid": true + }, + { + "description": "object with one property", + "data": {"bar": 2}, + "valid": true + } + ] + }, + { + "description": "multiple dependencies", + "schema": { + "dependencies": {"quux": ["foo", "bar"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependants", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "with dependencies", + "data": {"foo": 1, "bar": 2, "quux": 3}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"foo": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing other dependency", + "data": {"bar": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing both dependencies", + "data": {"quux": 1}, + "valid": false + } + ] + }, + { + "description": "multiple dependencies subschema", + "schema": { + "dependencies": { + "bar": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "integer"} + } + } + } + }, + "tests": [ + { + "description": "valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "no dependency", + "data": {"foo": "quux"}, + "valid": true + }, + { + "description": "wrong type", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "dependencies with boolean subschemas", + "schema": { + "dependencies": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "object with property having schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property having schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/enum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/enum.json new file mode 100644 index 0000000..f124436 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/enum.json @@ -0,0 +1,72 @@ +[ + { + "description": "simple enum validation", + "schema": {"enum": [1, 2, 3]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": 1, + "valid": true + }, + { + "description": "something else is invalid", + "data": 4, + "valid": false + } + ] + }, + { + "description": "heterogeneous enum validation", + "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": [], + "valid": true + }, + { + "description": "something else is invalid", + "data": null, + "valid": false + }, + { + "description": "objects are deep compared", + "data": {"foo": false}, + "valid": false + } + ] + }, + { + "description": "enums in properties", + "schema": { + "type":"object", + "properties": { + "foo": {"enum":["foo"]}, + "bar": {"enum":["bar"]} + }, + "required": ["bar"] + }, + "tests": [ + { + "description": "both properties are valid", + "data": {"foo":"foo", "bar":"bar"}, + "valid": true + }, + { + "description": "missing optional property is valid", + "data": {"bar":"bar"}, + "valid": true + }, + { + "description": "missing required property is invalid", + "data": {"foo":"foo"}, + "valid": false + }, + { + "description": "missing all properties is invalid", + "data": {}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMaximum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMaximum.json new file mode 100644 index 0000000..dc3cd70 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMaximum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMaximum validation", + "schema": { + "exclusiveMaximum": 3.0 + }, + "tests": [ + { + "description": "below the exclusiveMaximum is valid", + "data": 2.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 3.0, + "valid": false + }, + { + "description": "above the exclusiveMaximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMinimum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMinimum.json new file mode 100644 index 0000000..b38d7ec --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/exclusiveMinimum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMinimum validation", + "schema": { + "exclusiveMinimum": 1.1 + }, + "tests": [ + { + "description": "above the exclusiveMinimum is valid", + "data": 1.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "below the exclusiveMinimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/if-then-else.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/if-then-else.json new file mode 100644 index 0000000..18bd1f7 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/if-then-else.json @@ -0,0 +1,188 @@ +[ + { + "description": "ignore if without then or else", + "schema": { + "if": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone if", + "data": 0, + "valid": true + }, + { + "description": "valid when invailid against lone if", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "ignore then without if", + "schema": { + "then": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone then", + "data": 0, + "valid": true + }, + { + "description": "valid when invailid against lone then", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "ignore else without if", + "schema": { + "else": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone else", + "data": 0, + "valid": true + }, + { + "description": "valid when invailid against lone else", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "if and then without else", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + } + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "valid": true + }, + { + "description": "invalid through then", + "data": -100, + "valid": false + }, + { + "description": "valid when if test fails", + "data": 3, + "valid": true + } + ] + }, + { + "description": "if and else without then", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "else": { + "multipleOf": 2 + } + }, + "tests": [ + { + "description": "valid when if test passes", + "data": -1, + "valid": true + }, + { + "description": "valid through else", + "data": 4, + "valid": true + }, + { + "description": "invalid through else", + "data": 3, + "valid": false + } + ] + }, + { + "description": "validate against correct branch, then vs else", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + }, + "else": { + "multipleOf": 2 + } + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "valid": true + }, + { + "description": "invalid through then", + "data": -100, + "valid": false + }, + { + "description": "valid through else", + "data": 4, + "valid": true + }, + { + "description": "invalid through else", + "data": 3, + "valid": false + } + ] + }, + { + "description": "non-interference across combined schemas", + "schema": { + "allOf": [ + { + "if": { + "exclusiveMaximum": 0 + } + }, + { + "then": { + "minimum": -10 + } + }, + { + "else": { + "multipleOf": 2 + } + } + ] + }, + "tests": [ + { + "description": "valid, but woud have been invalid through then", + "data": -100, + "valid": true + }, + { + "description": "valid, but would have been invalid through else", + "data": 3, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/items.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/items.json new file mode 100644 index 0000000..13a6a11 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/items.json @@ -0,0 +1,133 @@ +[ + { + "description": "a schema given for items", + "schema": { + "items": {"type": "integer"} + }, + "tests": [ + { + "description": "valid items", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "wrong type of items", + "data": [1, "x"], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "length": 1 + }, + "valid": true + } + ] + }, + { + "description": "an array of schemas for items", + "schema": { + "items": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": false + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "items with boolean schema (true)", + "schema": {"items": true}, + "tests": [ + { + "description": "any array is valid", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schema (false)", + "schema": {"items": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": [ 1, "foo", true ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schemas", + "schema": { + "items": [true, false] + }, + "tests": [ + { + "description": "array with one item is valid", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with two items is invalid", + "data": [ 1, "foo" ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxItems.json new file mode 100644 index 0000000..3b53a6b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "maxItems validation", + "schema": {"maxItems": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": [1], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "too long is invalid", + "data": [1, 2, 3], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "foobar", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxLength.json new file mode 100644 index 0000000..811d35b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "maxLength validation", + "schema": {"maxLength": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too long is invalid", + "data": "foo", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + }, + { + "description": "two supplementary Unicode code points is long enough", + "data": "\uD83D\uDCA9\uD83D\uDCA9", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxProperties.json new file mode 100644 index 0000000..513731e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maxProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "maxProperties validation", + "schema": {"maxProperties": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "too long is invalid", + "data": {"foo": 1, "bar": 2, "baz": 3}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maximum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maximum.json new file mode 100644 index 0000000..8150984 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/maximum.json @@ -0,0 +1,28 @@ +[ + { + "description": "maximum validation", + "schema": {"maximum": 3.0}, + "tests": [ + { + "description": "below the maximum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 3.0, + "valid": true + }, + { + "description": "above the maximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minItems.json new file mode 100644 index 0000000..ed51188 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "minItems validation", + "schema": {"minItems": 1}, + "tests": [ + { + "description": "longer is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1], + "valid": true + }, + { + "description": "too short is invalid", + "data": [], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minLength.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minLength.json new file mode 100644 index 0000000..3f09158 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "minLength validation", + "schema": {"minLength": 2}, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too short is invalid", + "data": "f", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 1, + "valid": true + }, + { + "description": "one supplementary Unicode code point is not long enough", + "data": "\uD83D\uDCA9", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minProperties.json new file mode 100644 index 0000000..49a0726 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "minProperties validation", + "schema": {"minProperties": 1}, + "tests": [ + { + "description": "longer is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "too short is invalid", + "data": {}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minimum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minimum.json new file mode 100644 index 0000000..bd1e95b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/minimum.json @@ -0,0 +1,28 @@ +[ + { + "description": "minimum validation", + "schema": {"minimum": 1.1}, + "tests": [ + { + "description": "above the minimum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 1.1, + "valid": true + }, + { + "description": "below the minimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/multipleOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/multipleOf.json new file mode 100644 index 0000000..ca3b761 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/multipleOf.json @@ -0,0 +1,60 @@ +[ + { + "description": "by int", + "schema": {"multipleOf": 2}, + "tests": [ + { + "description": "int by int", + "data": 10, + "valid": true + }, + { + "description": "int by int fail", + "data": 7, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "by number", + "schema": {"multipleOf": 1.5}, + "tests": [ + { + "description": "zero is multiple of anything", + "data": 0, + "valid": true + }, + { + "description": "4.5 is multiple of 1.5", + "data": 4.5, + "valid": true + }, + { + "description": "35 is not multiple of 1.5", + "data": 35, + "valid": false + } + ] + }, + { + "description": "by small number", + "schema": {"multipleOf": 0.0001}, + "tests": [ + { + "description": "0.0075 is multiple of 0.0001", + "data": 0.0075, + "valid": true + }, + { + "description": "0.00751 is not multiple of 0.0001", + "data": 0.00751, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/not.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/not.json new file mode 100644 index 0000000..98de0ed --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/not.json @@ -0,0 +1,117 @@ +[ + { + "description": "not", + "schema": { + "not": {"type": "integer"} + }, + "tests": [ + { + "description": "allowed", + "data": "foo", + "valid": true + }, + { + "description": "disallowed", + "data": 1, + "valid": false + } + ] + }, + { + "description": "not multiple types", + "schema": { + "not": {"type": ["integer", "boolean"]} + }, + "tests": [ + { + "description": "valid", + "data": "foo", + "valid": true + }, + { + "description": "mismatch", + "data": 1, + "valid": false + }, + { + "description": "other mismatch", + "data": true, + "valid": false + } + ] + }, + { + "description": "not more complex schema", + "schema": { + "not": { + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "tests": [ + { + "description": "match", + "data": 1, + "valid": true + }, + { + "description": "other match", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "mismatch", + "data": {"foo": "bar"}, + "valid": false + } + ] + }, + { + "description": "forbidden property", + "schema": { + "properties": { + "foo": { + "not": {} + } + } + }, + "tests": [ + { + "description": "property present", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "property absent", + "data": {"bar": 1, "baz": 2}, + "valid": true + } + ] + }, + { + "description": "not with boolean schema true", + "schema": {"not": true}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "not with boolean schema false", + "schema": {"not": false}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/oneOf.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/oneOf.json new file mode 100644 index 0000000..bc4295c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/oneOf.json @@ -0,0 +1,153 @@ +[ + { + "description": "oneOf", + "schema": { + "oneOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": 1, + "valid": true + }, + { + "description": "second oneOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both oneOf valid", + "data": 3, + "valid": false + }, + { + "description": "neither oneOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "oneOf with base schema", + "schema": { + "type": "string", + "oneOf" : [ + { + "minLength": 2 + }, + { + "maxLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one oneOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both oneOf valid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all true", + "schema": {"oneOf": [true, true, true]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, one true", + "schema": {"oneOf": [true, false, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "oneOf with boolean schemas, more than one true", + "schema": {"oneOf": [true, true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all false", + "schema": {"oneOf": [false, false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf complex types", + "schema": { + "oneOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second oneOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both oneOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": false + }, + { + "description": "neither oneOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/bignum.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/bignum.json new file mode 100644 index 0000000..fac275e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/bignum.json @@ -0,0 +1,105 @@ +[ + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "integer", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": {"type": "number"}, + "tests": [ + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": {"type": "string"}, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"maximum": 18446744073709551615}, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "exclusiveMaximum": 972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": {"minimum": -18446744073709551615}, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "exclusiveMinimum": -972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/content.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/content.json new file mode 100644 index 0000000..6a98f11 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/content.json @@ -0,0 +1,62 @@ +[ + { + "description": "validation of string-encoded content based on media type", + "schema": { + "contentMediaType": "application/json" + }, + "tests": [ + { + "description": "a valid JSON document", + "data": "{\"foo\": \"bar\"}", + "valid": true + }, + { + "description": "an invalid JSON document", + "data": "{:}", + "valid": false + } + ] + }, + { + "description": "validation of binary string-encoding", + "schema": { + "contentEncoding": "base64" + }, + "tests": [ + { + "description": "a valid base64 string", + "data": "eyJmb28iOiAiYmFyIn0K", + "valid": true + }, + { + "description": "an invalid base64 string (% is not a valid character)", + "data": "eyJmb28iOi%iYmFyIn0K", + "valid": false + } + ] + }, + { + "description": "validation of binary-encoded media type documents", + "schema": { + "contentMediaType": "application/json", + "contentEncoding": "base64" + }, + "tests": [ + { + "description": "a valid base64-encoded JSON document", + "data": "eyJmb28iOiAiYmFyIn0K", + "valid": true + }, + { + "description": "a validly-encoded invalid JSON document", + "data": "ezp9Cg==", + "valid": false + }, + { + "description": "an invalid base64 string that is valid JSON", + "data": "{}", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/ecmascript-regex.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/ecmascript-regex.json new file mode 100644 index 0000000..08dc936 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/ecmascript-regex.json @@ -0,0 +1,13 @@ +[ + { + "description": "ECMA 262 regex non-compliance", + "schema": { "format": "regex" }, + "tests": [ + { + "description": "ECMA 262 has no support for \\Z anchor from .NET", + "data": "^\\S(|(.|\\n)*\\S)\\Z", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date-time.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date-time.json new file mode 100644 index 0000000..b450fe6 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date-time.json @@ -0,0 +1,23 @@ +[ + { + "description": "validation of date-time strings", + "schema": {"format": "date-time"}, + "tests": [ + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date.json new file mode 100644 index 0000000..cd23baa --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/date.json @@ -0,0 +1,23 @@ +[ + { + "description": "validation of date strings", + "schema": {"format": "date"}, + "tests": [ + { + "description": "a valid date string", + "data": "1963-06-19", + "valid": true + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/email.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/email.json new file mode 100644 index 0000000..c837c84 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/email.json @@ -0,0 +1,18 @@ +[ + { + "description": "validation of e-mail addresses", + "schema": {"format": "email"}, + "tests": [ + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "valid": true + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/hostname.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/hostname.json new file mode 100644 index 0000000..d22e57d --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/hostname.json @@ -0,0 +1,33 @@ +[ + { + "description": "validation of host names", + "schema": {"format": "hostname"}, + "tests": [ + { + "description": "a valid host name", + "data": "www.example.com", + "valid": true + }, + { + "description": "a valid punycoded IDN hostname", + "data": "xn--4gbwdl.xn--wgbh1c", + "valid": true + }, + { + "description": "a host name starting with an illegal character", + "data": "-a-host-name-that-starts-with--", + "valid": false + }, + { + "description": "a host name containing illegal characters", + "data": "not_a_valid_host_name", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-email.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-email.json new file mode 100644 index 0000000..637409e --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-email.json @@ -0,0 +1,18 @@ +[ + { + "description": "validation of an internationalized e-mail addresses", + "schema": {"format": "idn-email"}, + "tests": [ + { + "description": "a valid idn e-mail (example@example.test in Hangul)", + "data": "실례@실례.테스트", + "valid": true + }, + { + "description": "an invalid idn e-mail address", + "data": "2962", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-hostname.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-hostname.json new file mode 100644 index 0000000..3291820 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/idn-hostname.json @@ -0,0 +1,28 @@ +[ + { + "description": "validation of internationalized host names", + "schema": {"format": "idn-hostname"}, + "tests": [ + { + "description": "a valid host name (example.test in Hangul)", + "data": "실례.테스트", + "valid": true + }, + { + "description": "illegal first char U+302E Hangul single dot tone mark", + "data": "〮실례.테스트", + "valid": false + }, + { + "description": "contains illegal char U+302E Hangul single dot tone mark", + "data": "실〮례.테스트", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv4.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv4.json new file mode 100644 index 0000000..661148a --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv4.json @@ -0,0 +1,33 @@ +[ + { + "description": "validation of IP addresses", + "schema": {"format": "ipv4"}, + "tests": [ + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv6.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv6.json new file mode 100644 index 0000000..f67559b --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/ipv6.json @@ -0,0 +1,28 @@ +[ + { + "description": "validation of IPv6 addresses", + "schema": {"format": "ipv6"}, + "tests": [ + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": false + }, + { + "description": "an IPv6 address with too many components", + "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri-reference.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri-reference.json new file mode 100644 index 0000000..1fd779c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri-reference.json @@ -0,0 +1,43 @@ +[ + { + "description": "validation of IRI References", + "schema": {"format": "iri-reference"}, + "tests": [ + { + "description": "a valid IRI", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid protocol-relative IRI Reference", + "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid relative IRI Reference", + "data": "/âππ", + "valid": true + }, + { + "description": "an invalid IRI Reference", + "data": "\\\\WINDOWS\\filëßåré", + "valid": false + }, + { + "description": "a valid IRI Reference", + "data": "âππ", + "valid": true + }, + { + "description": "a valid IRI fragment", + "data": "#ƒrägmênt", + "valid": true + }, + { + "description": "an invalid IRI fragment", + "data": "#ƒräg\\mênt", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri.json new file mode 100644 index 0000000..f9c8715 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/iri.json @@ -0,0 +1,48 @@ +[ + { + "description": "validation of IRIs", + "schema": {"format": "iri"}, + "tests": [ + { + "description": "a valid IRI with anchor tag", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid IRI with anchor tag and parantheses", + "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", + "valid": true + }, + { + "description": "a valid IRI with URL-encoded stuff", + "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid IRI with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid IRI based on IPv6", + "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "valid": true + }, + { + "description": "an invalid relative IRI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid IRI", + "data": "\\\\WINDOWS\\filëßåré", + "valid": false + }, + { + "description": "an invalid IRI though valid IRI reference", + "data": "âππ", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/json-pointer.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/json-pointer.json new file mode 100644 index 0000000..65c2f06 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/json-pointer.json @@ -0,0 +1,168 @@ +[ + { + "description": "validation of JSON-pointers (JSON String Representation)", + "schema": {"format": "json-pointer"}, + "tests": [ + { + "description": "a valid JSON-pointer", + "data": "/foo/bar~0/baz~1/%a", + "valid": true + }, + { + "description": "not a valid JSON-pointer (~ not escaped)", + "data": "/foo/bar~", + "valid": false + }, + { + "description": "valid JSON-pointer with empty segment", + "data": "/foo//bar", + "valid": true + }, + { + "description": "valid JSON-pointer with the last empty segment", + "data": "/foo/bar/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #1", + "data": "", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #2", + "data": "/foo", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #3", + "data": "/foo/0", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #4", + "data": "/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #5", + "data": "/a~1b", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #6", + "data": "/c%d", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #7", + "data": "/e^f", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #8", + "data": "/g|h", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #9", + "data": "/i\\j", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #10", + "data": "/k\"l", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #11", + "data": "/ ", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #12", + "data": "/m~0n", + "valid": true + }, + { + "description": "valid JSON-pointer used adding to the last array position", + "data": "/foo/-", + "valid": true + }, + { + "description": "valid JSON-pointer (- used as object member name)", + "data": "/foo/-/bar", + "valid": true + }, + { + "description": "valid JSON-pointer (multiple escaped characters)", + "data": "/~1~0~0~1~1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #1", + "data": "/~1.1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #2", + "data": "/~0.1", + "valid": true + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", + "data": "#", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", + "data": "#/", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", + "data": "#a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #1", + "data": "/~0~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #2", + "data": "/~0/~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #1", + "data": "/~2", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #2", + "data": "/~-1", + "valid": false + }, + { + "description": "not a valid JSON-pointer (multiple characters not escaped)", + "data": "/~~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", + "data": "a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", + "data": "0", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3", + "data": "a/a", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/regex.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/regex.json new file mode 100644 index 0000000..d99d021 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/regex.json @@ -0,0 +1,18 @@ +[ + { + "description": "validation of regular expressions", + "schema": {"format": "regex"}, + "tests": [ + { + "description": "a valid regular expression", + "data": "([abc])+\\s+$", + "valid": true + }, + { + "description": "a regular expression with unclosed parens is invalid", + "data": "^(abc]", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/relative-json-pointer.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/relative-json-pointer.json new file mode 100644 index 0000000..ceeb743 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/relative-json-pointer.json @@ -0,0 +1,33 @@ +[ + { + "description": "validation of Relative JSON Pointers (RJP)", + "schema": {"format": "relative-json-pointer"}, + "tests": [ + { + "description": "a valid upwards RJP", + "data": "1", + "valid": true + }, + { + "description": "a valid downwards RJP", + "data": "0/foo/bar", + "valid": true + }, + { + "description": "a valid up and then down RJP, with array index", + "data": "2/0/baz/1/zip", + "valid": true + }, + { + "description": "a valid RJP taking the member or index name", + "data": "0#", + "valid": true + }, + { + "description": "an invalid RJP that is a valid JSON Pointer", + "data": "/foo/bar", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/time.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/time.json new file mode 100644 index 0000000..4ec8a01 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/time.json @@ -0,0 +1,23 @@ +[ + { + "description": "validation of time strings", + "schema": {"format": "time"}, + "tests": [ + { + "description": "a valid time string", + "data": "08:30:06.283185Z", + "valid": true + }, + { + "description": "an invalid time string", + "data": "08:30:06 PST", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "01:01:01,1111", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-reference.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-reference.json new file mode 100644 index 0000000..e4c9eef --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-reference.json @@ -0,0 +1,43 @@ +[ + { + "description": "validation of URI References", + "schema": {"format": "uri-reference"}, + "tests": [ + { + "description": "a valid URI", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid relative URI Reference", + "data": "/abc", + "valid": true + }, + { + "description": "an invalid URI Reference", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "a valid URI Reference", + "data": "abc", + "valid": true + }, + { + "description": "a valid URI fragment", + "data": "#fragment", + "valid": true + }, + { + "description": "an invalid URI fragment", + "data": "#frag\\ment", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-template.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-template.json new file mode 100644 index 0000000..d8396a5 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri-template.json @@ -0,0 +1,30 @@ +[ + { + "description": "format: uri-template", + "schema": { + "format": "uri-template" + }, + "tests": [ + { + "description": "a valid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term}", + "valid": true + }, + { + "description": "an invalid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term", + "valid": false + }, + { + "description": "a valid uri-template without variables", + "data": "http://example.com/dictionary", + "valid": true + }, + { + "description": "a valid relative uri-template", + "data": "dictionary/{term:1}/{term}", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri.json new file mode 100644 index 0000000..25cc40c --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/format/uri.json @@ -0,0 +1,103 @@ +[ + { + "description": "validation of URIs", + "schema": {"format": "uri"}, + "tests": [ + { + "description": "a valid URL with anchor tag", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid URL with anchor tag and parantheses", + "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", + "valid": true + }, + { + "description": "a valid URL with URL-encoded stuff", + "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid puny-coded URL ", + "data": "http://xn--nw2a.xn--j6w193g/", + "valid": true + }, + { + "description": "a valid URL with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid URL based on IPv4", + "data": "http://223.255.255.254", + "valid": true + }, + { + "description": "a valid URL with ftp scheme", + "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "valid": true + }, + { + "description": "a valid URL for a simple text file", + "data": "http://www.ietf.org/rfc/rfc2396.txt", + "valid": true + }, + { + "description": "a valid URL ", + "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", + "valid": true + }, + { + "description": "a valid mailto URI", + "data": "mailto:John.Doe@example.com", + "valid": true + }, + { + "description": "a valid newsgroup URI", + "data": "news:comp.infosystems.www.servers.unix", + "valid": true + }, + { + "description": "a valid tel URI", + "data": "tel:+1-816-555-1212", + "valid": true + }, + { + "description": "a valid URN", + "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", + "valid": true + }, + { + "description": "an invalid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": false + }, + { + "description": "an invalid relative URI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid URI", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "an invalid URI though valid URI reference", + "data": "abc", + "valid": false + }, + { + "description": "an invalid URI with spaces", + "data": "http:// shouldfail.com", + "valid": false + }, + { + "description": "an invalid URI with spaces and missing scheme", + "data": ":// should fail", + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/zeroTerminatedFloats.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/zeroTerminatedFloats.json new file mode 100644 index 0000000..1bcdf96 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/optional/zeroTerminatedFloats.json @@ -0,0 +1,15 @@ +[ + { + "description": "some languages do not distinguish between different types of numeric value", + "schema": { + "type": "integer" + }, + "tests": [ + { + "description": "a float without fractional part is an integer", + "data": 1.0, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/pattern.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/pattern.json new file mode 100644 index 0000000..25e7299 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/pattern.json @@ -0,0 +1,34 @@ +[ + { + "description": "pattern validation", + "schema": {"pattern": "^a*$"}, + "tests": [ + { + "description": "a matching pattern is valid", + "data": "aaa", + "valid": true + }, + { + "description": "a non-matching pattern is invalid", + "data": "abc", + "valid": false + }, + { + "description": "ignores non-strings", + "data": true, + "valid": true + } + ] + }, + { + "description": "pattern is not anchored", + "schema": {"pattern": "a+"}, + "tests": [ + { + "description": "matches a substring", + "data": "xxaayy", + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/patternProperties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/patternProperties.json new file mode 100644 index 0000000..1d04a16 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/patternProperties.json @@ -0,0 +1,151 @@ +[ + { + "description": + "patternProperties validates properties matching a regex", + "schema": { + "patternProperties": { + "f.*o": {"type": "integer"} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "multiple valid matches is valid", + "data": {"foo": 1, "foooooo" : 2}, + "valid": true + }, + { + "description": "a single invalid match is invalid", + "data": {"foo": "bar", "fooooo": 2}, + "valid": false + }, + { + "description": "multiple invalid matches is invalid", + "data": {"foo": "bar", "foooooo" : "baz"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["foo"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foo", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "multiple simultaneous patternProperties are validated", + "schema": { + "patternProperties": { + "a*": {"type": "integer"}, + "aaa*": {"maximum": 20} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"a": 21}, + "valid": true + }, + { + "description": "a simultaneous match is valid", + "data": {"aaaa": 18}, + "valid": true + }, + { + "description": "multiple matches is valid", + "data": {"a": 21, "aaaa": 18}, + "valid": true + }, + { + "description": "an invalid due to one is invalid", + "data": {"a": "bar"}, + "valid": false + }, + { + "description": "an invalid due to the other is invalid", + "data": {"aaaa": 31}, + "valid": false + }, + { + "description": "an invalid due to both is invalid", + "data": {"aaa": "foo", "aaaa": 31}, + "valid": false + } + ] + }, + { + "description": "regexes are not anchored by default and are case sensitive", + "schema": { + "patternProperties": { + "[0-9]{2,}": { "type": "boolean" }, + "X_": { "type": "string" } + } + }, + "tests": [ + { + "description": "non recognized members are ignored", + "data": { "answer 1": "42" }, + "valid": true + }, + { + "description": "recognized members are accounted for", + "data": { "a31b": null }, + "valid": false + }, + { + "description": "regexes are case sensitive", + "data": { "a_x_3": 3 }, + "valid": true + }, + { + "description": "regexes are case sensitive, 2", + "data": { "a_X_3": 3 }, + "valid": false + } + ] + }, + { + "description": "patternProperties with boolean schemas", + "schema": { + "patternProperties": { + "f.*": true, + "b.*": false + } + }, + "tests": [ + { + "description": "object with property matching schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property matching schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/properties.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/properties.json new file mode 100644 index 0000000..c8ad719 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/properties.json @@ -0,0 +1,128 @@ +[ + { + "description": "object properties validation", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "string"} + } + }, + "tests": [ + { + "description": "both properties present and valid is valid", + "data": {"foo": 1, "bar": "baz"}, + "valid": true + }, + { + "description": "one property invalid is invalid", + "data": {"foo": 1, "bar": {}}, + "valid": false + }, + { + "description": "both properties invalid is invalid", + "data": {"foo": [], "bar": {}}, + "valid": false + }, + { + "description": "doesn't invalidate other properties", + "data": {"quux": []}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": + "properties, patternProperties, additionalProperties interaction", + "schema": { + "properties": { + "foo": {"type": "array", "maxItems": 3}, + "bar": {"type": "array"} + }, + "patternProperties": {"f.o": {"minItems": 2}}, + "additionalProperties": {"type": "integer"} + }, + "tests": [ + { + "description": "property validates property", + "data": {"foo": [1, 2]}, + "valid": true + }, + { + "description": "property invalidates property", + "data": {"foo": [1, 2, 3, 4]}, + "valid": false + }, + { + "description": "patternProperty invalidates property", + "data": {"foo": []}, + "valid": false + }, + { + "description": "patternProperty validates nonproperty", + "data": {"fxo": [1, 2]}, + "valid": true + }, + { + "description": "patternProperty invalidates nonproperty", + "data": {"fxo": []}, + "valid": false + }, + { + "description": "additionalProperty ignores property", + "data": {"bar": []}, + "valid": true + }, + { + "description": "additionalProperty validates others", + "data": {"quux": 3}, + "valid": true + }, + { + "description": "additionalProperty invalidates others", + "data": {"quux": "foo"}, + "valid": false + } + ] + }, + { + "description": "properties with boolean schema", + "schema": { + "properties": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "no property present is valid", + "data": {}, + "valid": true + }, + { + "description": "only 'true' property present is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "only 'false' property present is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "both properties present is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/propertyNames.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/propertyNames.json new file mode 100644 index 0000000..8423690 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/propertyNames.json @@ -0,0 +1,78 @@ +[ + { + "description": "propertyNames validation", + "schema": { + "propertyNames": {"maxLength": 3} + }, + "tests": [ + { + "description": "all property names valid", + "data": { + "f": {}, + "foo": {} + }, + "valid": true + }, + { + "description": "some property names invalid", + "data": { + "foo": {}, + "foobar": {} + }, + "valid": false + }, + { + "description": "object without properties is valid", + "data": {}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [1, 2, 3, 4], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema true", + "schema": {"propertyNames": true}, + "tests": [ + { + "description": "object with any properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema false", + "schema": {"propertyNames": false}, + "tests": [ + { + "description": "object with any properties is invalid", + "data": {"foo": 1}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/ref.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/ref.json new file mode 100644 index 0000000..7579507 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/ref.json @@ -0,0 +1,332 @@ +[ + { + "description": "root pointer ref", + "schema": { + "properties": { + "foo": {"$ref": "#"} + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "match", + "data": {"foo": false}, + "valid": true + }, + { + "description": "recursive match", + "data": {"foo": {"foo": false}}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": false}, + "valid": false + }, + { + "description": "recursive mismatch", + "data": {"foo": {"bar": false}}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to object", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"$ref": "#/properties/foo"} + } + }, + "tests": [ + { + "description": "match", + "data": {"bar": 3}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": true}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to array", + "schema": { + "items": [ + {"type": "integer"}, + {"$ref": "#/items/0"} + ] + }, + "tests": [ + { + "description": "match array", + "data": [1, 2], + "valid": true + }, + { + "description": "mismatch array", + "data": [1, "foo"], + "valid": false + } + ] + }, + { + "description": "escaped pointer ref", + "schema": { + "tilda~field": {"type": "integer"}, + "slash/field": {"type": "integer"}, + "percent%field": {"type": "integer"}, + "properties": { + "tilda": {"$ref": "#/tilda~0field"}, + "slash": {"$ref": "#/slash~1field"}, + "percent": {"$ref": "#/percent%25field"} + } + }, + "tests": [ + { + "description": "slash invalid", + "data": {"slash": "aoeu"}, + "valid": false + }, + { + "description": "tilda invalid", + "data": {"tilda": "aoeu"}, + "valid": false + }, + { + "description": "percent invalid", + "data": {"percent": "aoeu"}, + "valid": false + }, + { + "description": "slash valid", + "data": {"slash": 123}, + "valid": true + }, + { + "description": "tilda valid", + "data": {"tilda": 123}, + "valid": true + }, + { + "description": "percent valid", + "data": {"percent": 123}, + "valid": true + } + ] + }, + { + "description": "nested refs", + "schema": { + "definitions": { + "a": {"type": "integer"}, + "b": {"$ref": "#/definitions/a"}, + "c": {"$ref": "#/definitions/b"} + }, + "$ref": "#/definitions/c" + }, + "tests": [ + { + "description": "nested ref valid", + "data": 5, + "valid": true + }, + { + "description": "nested ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref overrides any sibling keywords", + "schema": { + "definitions": { + "reffed": { + "type": "array" + } + }, + "properties": { + "foo": { + "$ref": "#/definitions/reffed", + "maxItems": 2 + } + } + }, + "tests": [ + { + "description": "ref valid", + "data": { "foo": [] }, + "valid": true + }, + { + "description": "ref valid, maxItems ignored", + "data": { "foo": [ 1, 2, 3] }, + "valid": true + }, + { + "description": "ref invalid", + "data": { "foo": "string" }, + "valid": false + } + ] + }, + { + "description": "remote ref, containing refs itself", + "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, + "tests": [ + { + "description": "remote ref valid", + "data": {"minLength": 1}, + "valid": true + }, + { + "description": "remote ref invalid", + "data": {"minLength": -1}, + "valid": false + } + ] + }, + { + "description": "property named $ref that is not a reference", + "schema": { + "properties": { + "$ref": {"type": "string"} + } + }, + "tests": [ + { + "description": "property named $ref valid", + "data": {"$ref": "a"}, + "valid": true + }, + { + "description": "property named $ref invalid", + "data": {"$ref": 2}, + "valid": false + } + ] + }, + { + "description": "$ref to boolean schema true", + "schema": { + "$ref": "#/definitions/bool", + "definitions": { + "bool": true + } + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "$ref to boolean schema false", + "schema": { + "$ref": "#/definitions/bool", + "definitions": { + "bool": false + } + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "Recursive references between schemas", + "schema": { + "$id": "http://localhost:1234/tree", + "description": "tree of nodes", + "type": "object", + "properties": { + "meta": {"type": "string"}, + "nodes": { + "type": "array", + "items": {"$ref": "node"} + } + }, + "required": ["meta", "nodes"], + "definitions": { + "node": { + "$id": "http://localhost:1234/node", + "description": "node", + "type": "object", + "properties": { + "value": {"type": "number"}, + "subtree": {"$ref": "tree"} + }, + "required": ["value"] + } + } + }, + "tests": [ + { + "description": "valid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 1.1}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": true + }, + { + "description": "invalid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": "string is invalid"}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/refRemote.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/refRemote.json new file mode 100644 index 0000000..819d326 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/refRemote.json @@ -0,0 +1,171 @@ +[ + { + "description": "remote ref", + "schema": {"$ref": "http://localhost:1234/integer.json"}, + "tests": [ + { + "description": "remote ref valid", + "data": 1, + "valid": true + }, + { + "description": "remote ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "fragment within remote ref", + "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, + "tests": [ + { + "description": "remote fragment valid", + "data": 1, + "valid": true + }, + { + "description": "remote fragment invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref within remote ref", + "schema": { + "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" + }, + "tests": [ + { + "description": "ref within ref valid", + "data": 1, + "valid": true + }, + { + "description": "ref within ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "base URI change", + "schema": { + "$id": "http://localhost:1234/", + "items": { + "$id": "folder/", + "items": {"$ref": "folderInteger.json"} + } + }, + "tests": [ + { + "description": "base URI change ref valid", + "data": [[1]], + "valid": true + }, + { + "description": "base URI change ref invalid", + "data": [["a"]], + "valid": false + } + ] + }, + { + "description": "base URI change - change folder", + "schema": { + "$id": "http://localhost:1234/scope_change_defs1.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz"} + }, + "definitions": { + "baz": { + "$id": "folder/", + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "base URI change - change folder in subschema", + "schema": { + "$id": "http://localhost:1234/scope_change_defs2.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz/definitions/bar"} + }, + "definitions": { + "baz": { + "$id": "folder/", + "definitions": { + "bar": { + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "root ref in remote ref", + "schema": { + "$id": "http://localhost:1234/object", + "type": "object", + "properties": { + "name": {"$ref": "name.json#/definitions/orNull"} + } + }, + "tests": [ + { + "description": "string is valid", + "data": { + "name": "foo" + }, + "valid": true + }, + { + "description": "null is valid", + "data": { + "name": null + }, + "valid": true + }, + { + "description": "object is invalid", + "data": { + "name": { + "name": null + } + }, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/required.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/required.json new file mode 100644 index 0000000..bd96907 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/required.json @@ -0,0 +1,70 @@ +[ + { + "description": "required validation", + "schema": { + "properties": { + "foo": {}, + "bar": {} + }, + "required": ["foo"] + }, + "tests": [ + { + "description": "present required property is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "non-present required property is invalid", + "data": {"bar": 1}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "required default validation", + "schema": { + "properties": { + "foo": {} + } + }, + "tests": [ + { + "description": "not required by default", + "data": {}, + "valid": true + } + ] + }, + { + "description": "required with empty array", + "schema": { + "properties": { + "foo": {} + }, + "required": [] + }, + "tests": [ + { + "description": "property not required", + "data": {}, + "valid": true + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/type.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/type.json new file mode 100644 index 0000000..6129374 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/type.json @@ -0,0 +1,345 @@ +[ + { + "description": "integer type matches integers", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "an integer is an integer", + "data": 1, + "valid": true + }, + { + "description": "a float is not an integer", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an integer", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not an integer, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not an integer", + "data": {}, + "valid": false + }, + { + "description": "an array is not an integer", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an integer", + "data": true, + "valid": false + }, + { + "description": "null is not an integer", + "data": null, + "valid": false + } + ] + }, + { + "description": "number type matches numbers", + "schema": {"type": "number"}, + "tests": [ + { + "description": "an integer is a number", + "data": 1, + "valid": true + }, + { + "description": "a float is a number", + "data": 1.1, + "valid": true + }, + { + "description": "a string is not a number", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not a number, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not a number", + "data": {}, + "valid": false + }, + { + "description": "an array is not a number", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a number", + "data": true, + "valid": false + }, + { + "description": "null is not a number", + "data": null, + "valid": false + } + ] + }, + { + "description": "string type matches strings", + "schema": {"type": "string"}, + "tests": [ + { + "description": "1 is not a string", + "data": 1, + "valid": false + }, + { + "description": "a float is not a string", + "data": 1.1, + "valid": false + }, + { + "description": "a string is a string", + "data": "foo", + "valid": true + }, + { + "description": "a string is still a string, even if it looks like a number", + "data": "1", + "valid": true + }, + { + "description": "an object is not a string", + "data": {}, + "valid": false + }, + { + "description": "an array is not a string", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a string", + "data": true, + "valid": false + }, + { + "description": "null is not a string", + "data": null, + "valid": false + } + ] + }, + { + "description": "object type matches objects", + "schema": {"type": "object"}, + "tests": [ + { + "description": "an integer is not an object", + "data": 1, + "valid": false + }, + { + "description": "a float is not an object", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an object", + "data": "foo", + "valid": false + }, + { + "description": "an object is an object", + "data": {}, + "valid": true + }, + { + "description": "an array is not an object", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an object", + "data": true, + "valid": false + }, + { + "description": "null is not an object", + "data": null, + "valid": false + } + ] + }, + { + "description": "array type matches arrays", + "schema": {"type": "array"}, + "tests": [ + { + "description": "an integer is not an array", + "data": 1, + "valid": false + }, + { + "description": "a float is not an array", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an array", + "data": "foo", + "valid": false + }, + { + "description": "an object is not an array", + "data": {}, + "valid": false + }, + { + "description": "an array is an array", + "data": [], + "valid": true + }, + { + "description": "a boolean is not an array", + "data": true, + "valid": false + }, + { + "description": "null is not an array", + "data": null, + "valid": false + } + ] + }, + { + "description": "boolean type matches booleans", + "schema": {"type": "boolean"}, + "tests": [ + { + "description": "an integer is not a boolean", + "data": 1, + "valid": false + }, + { + "description": "a float is not a boolean", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not a boolean", + "data": "foo", + "valid": false + }, + { + "description": "an object is not a boolean", + "data": {}, + "valid": false + }, + { + "description": "an array is not a boolean", + "data": [], + "valid": false + }, + { + "description": "a boolean is a boolean", + "data": true, + "valid": true + }, + { + "description": "null is not a boolean", + "data": null, + "valid": false + } + ] + }, + { + "description": "null type matches only the null object", + "schema": {"type": "null"}, + "tests": [ + { + "description": "an integer is not null", + "data": 1, + "valid": false + }, + { + "description": "a float is not null", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not null", + "data": "foo", + "valid": false + }, + { + "description": "an object is not null", + "data": {}, + "valid": false + }, + { + "description": "an array is not null", + "data": [], + "valid": false + }, + { + "description": "a boolean is not null", + "data": true, + "valid": false + }, + { + "description": "null is null", + "data": null, + "valid": true + } + ] + }, + { + "description": "multiple types can be specified in an array", + "schema": {"type": ["integer", "string"]}, + "tests": [ + { + "description": "an integer is valid", + "data": 1, + "valid": true + }, + { + "description": "a string is valid", + "data": "foo", + "valid": true + }, + { + "description": "a float is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "an object is invalid", + "data": {}, + "valid": false + }, + { + "description": "an array is invalid", + "data": [], + "valid": false + }, + { + "description": "a boolean is invalid", + "data": true, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/uniqueItems.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/uniqueItems.json new file mode 100644 index 0000000..c1f4ab9 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/draft7/uniqueItems.json @@ -0,0 +1,79 @@ +[ + { + "description": "uniqueItems validation", + "schema": {"uniqueItems": true}, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "non-unique array of integers is invalid", + "data": [1, 1], + "valid": false + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [1.0, 1.00, 1], + "valid": false + }, + { + "description": "unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "baz"}], + "valid": true + }, + { + "description": "non-unique array of objects is invalid", + "data": [{"foo": "bar"}, {"foo": "bar"}], + "valid": false + }, + { + "description": "unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : false}}} + ], + "valid": true + }, + { + "description": "non-unique array of nested objects is invalid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : true}}} + ], + "valid": false + }, + { + "description": "unique array of arrays is valid", + "data": [["foo"], ["bar"]], + "valid": true + }, + { + "description": "non-unique array of arrays is invalid", + "data": [["foo"], ["foo"]], + "valid": false + }, + { + "description": "1 and true are unique", + "data": [1, true], + "valid": true + }, + { + "description": "0 and false are unique", + "data": [0, false], + "valid": true + }, + { + "description": "unique heterogeneous types are valid", + "data": [{}, [1], true, null, 1], + "valid": true + }, + { + "description": "non-unique heterogeneous types are invalid", + "data": [{}, [1], true, null, {}, 1], + "valid": false + } + ] + } +] diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_6.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/extra/fragment_schema.json similarity index 100% rename from vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/ref/schema_6.json rename to vendor/github.com/xeipuuv/gojsonschema/testdata/extra/fragment_schema.json diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/folder/folderInteger.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/folder/folderInteger.json similarity index 100% rename from vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/folder/folderInteger.json rename to vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/folder/folderInteger.json diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/integer.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/integer.json similarity index 100% rename from vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/integer.json rename to vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/integer.json diff --git a/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/name.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/name.json new file mode 100644 index 0000000..19ba093 --- /dev/null +++ b/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/name.json @@ -0,0 +1,11 @@ +{ + "definitions": { + "orNull": { + "anyOf": [ + {"type": "null"}, + {"$ref": "#"} + ] + } + }, + "type": "string" +} diff --git a/vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/subSchemas.json b/vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/subSchemas.json similarity index 100% rename from vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/refRemote/remoteFiles/subSchemas.json rename to vendor/github.com/xeipuuv/gojsonschema/testdata/remotes/subSchemas.json diff --git a/vendor/github.com/xeipuuv/gojsonschema/utils.go b/vendor/github.com/xeipuuv/gojsonschema/utils.go index 26cf75e..cc3100a 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/utils.go +++ b/vendor/github.com/xeipuuv/gojsonschema/utils.go @@ -29,17 +29,23 @@ import ( "encoding/json" "fmt" "math" + "math/big" "reflect" - "strconv" ) -func isKind(what interface{}, kind reflect.Kind) bool { +func isKind(what interface{}, kinds ...reflect.Kind) bool { target := what if isJsonNumber(what) { // JSON Numbers are strings! target = *mustBeNumber(what) } - return reflect.ValueOf(target).Kind() == kind + targetKind := reflect.ValueOf(target).Kind() + for _, kind := range kinds { + if targetKind == kind { + return true + } + } + return false } func existsMapKey(m map[string]interface{}, k string) bool { @@ -67,6 +73,28 @@ func marshalToJsonString(value interface{}) (*string, error) { return &sBytes, nil } +func marshalWithoutNumber(value interface{}) (*string, error) { + + // The JSON is decoded using https://golang.org/pkg/encoding/json/#Decoder.UseNumber + // This means the numbers are internally still represented as strings and therefore 1.00 is unequal to 1 + // One way to eliminate these differences is to decode and encode the JSON one more time without Decoder.UseNumber + // so that these differences in representation are removed + + jsonString, err := marshalToJsonString(value) + if err != nil { + return nil, err + } + + var document interface{} + + err = json.Unmarshal([]byte(*jsonString), &document) + if err != nil { + return nil, err + } + + return marshalToJsonString(document) +} + func isJsonNumber(what interface{}) bool { switch what.(type) { @@ -78,21 +106,13 @@ func isJsonNumber(what interface{}) bool { return false } -func checkJsonNumber(what interface{}) (isValidFloat64 bool, isValidInt64 bool, isValidInt32 bool) { +func checkJsonInteger(what interface{}) (isInt bool) { jsonNumber := what.(json.Number) - f64, errFloat64 := jsonNumber.Float64() - s64 := strconv.FormatFloat(f64, 'f', -1, 64) - _, errInt64 := strconv.ParseInt(s64, 10, 64) + bigFloat, isValidNumber := new(big.Float).SetString(string(jsonNumber)) - isValidFloat64 = errFloat64 == nil - isValidInt64 = errInt64 == nil - - _, errInt32 := strconv.ParseInt(s64, 10, 32) - isValidInt32 = isValidInt64 && errInt32 == nil - - return + return isValidNumber && bigFloat.IsInt() } @@ -117,9 +137,9 @@ func mustBeInteger(what interface{}) *int { number := what.(json.Number) - _, _, isValidInt32 := checkJsonNumber(number) + isInt := checkJsonInteger(number) - if isValidInt32 { + if isInt { int64Value, err := number.Int64() if err != nil { @@ -138,15 +158,13 @@ func mustBeInteger(what interface{}) *int { return nil } -func mustBeNumber(what interface{}) *float64 { +func mustBeNumber(what interface{}) *big.Float { if isJsonNumber(what) { - number := what.(json.Number) - float64Value, err := number.Float64() - - if err == nil { - return &float64Value + float64Value, success := new(big.Float).SetString(string(number)) + if success { + return float64Value } else { return nil } diff --git a/vendor/github.com/xeipuuv/gojsonschema/utils_test.go b/vendor/github.com/xeipuuv/gojsonschema/utils_test.go index 489577d..2450d93 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/utils_test.go +++ b/vendor/github.com/xeipuuv/gojsonschema/utils_test.go @@ -26,6 +26,7 @@ package gojsonschema import ( + "encoding/json" "github.com/stretchr/testify/assert" "math" "testing" @@ -62,3 +63,29 @@ func TestResultErrorFormatNumber(t *testing.T) { assert.Equal(t, "-4.6116860184273876e+07", resultErrorFormatNumber(-4.611686018427387904e7)) } + +func TestCheckJsonNumber(t *testing.T) { + var testCases = []struct { + isInt bool + value json.Number + }{ + {true, "0"}, + {true, "2147483647"}, + {true, "-2147483648"}, + {true, "9223372036854775807"}, + {true, "-9223372036854775808"}, + {true, "1.0e+2"}, + {true, "1.0e+10"}, + {true, "-1.0e+2"}, + {true, "-1.0e+10"}, + {false, "1.0e-2"}, + {false, "number"}, + {false, "123number"}, + } + + for _, testCase := range testCases { + assert.Equal(t, testCase.isInt, checkJsonInteger(testCase.value)) + assert.Equal(t, testCase.isInt, checkJsonInteger(testCase.value)) + } + +} diff --git a/vendor/github.com/xeipuuv/gojsonschema/validation.go b/vendor/github.com/xeipuuv/gojsonschema/validation.go index 9afea25..2f1e7df 100644 --- a/vendor/github.com/xeipuuv/gojsonschema/validation.go +++ b/vendor/github.com/xeipuuv/gojsonschema/validation.go @@ -27,6 +27,7 @@ package gojsonschema import ( "encoding/json" + "math/big" "reflect" "regexp" "strconv" @@ -60,24 +61,27 @@ func (v *Schema) Validate(l JSONLoader) (*Result, error) { return nil, err } + return v.validateDocument(root), nil +} + +func (v *Schema) validateDocument(root interface{}) *Result { // begin validation result := &Result{} - context := newJsonContext(STRING_CONTEXT_ROOT, nil) + context := NewJsonContext(STRING_CONTEXT_ROOT, nil) v.rootSchema.validateRecursive(v.rootSchema, root, result, context) - return result, nil - + return result } -func (v *subSchema) subValidateWithContext(document interface{}, context *jsonContext) *Result { +func (v *subSchema) subValidateWithContext(document interface{}, context *JsonContext) *Result { result := &Result{} v.validateRecursive(v, document, result, context) return result } // Walker function to validate the json recursively against the subSchema -func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *JsonContext) { if internalLogEnabled { internalLog("validateRecursive %s", context.String()) @@ -93,7 +97,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i // Check for null value if currentNode == nil { if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_NULL) { - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -114,18 +118,18 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i value := currentNode.(json.Number) - _, isValidInt64, _ := checkJsonNumber(value) + isInt := checkJsonInteger(value) - validType := currentSubSchema.types.Contains(TYPE_NUMBER) || (isValidInt64 && currentSubSchema.types.Contains(TYPE_INTEGER)) + validType := currentSubSchema.types.Contains(TYPE_NUMBER) || (isInt && currentSubSchema.types.Contains(TYPE_INTEGER)) if currentSubSchema.types.IsTyped() && !validType { givenType := TYPE_INTEGER - if !isValidInt64 { + if !isInt { givenType = TYPE_NUMBER } - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -154,7 +158,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i case reflect.Slice: if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_ARRAY) { - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -177,7 +181,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i case reflect.Map: if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_OBJECT) { - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -202,7 +206,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i for _, pSchema := range currentSubSchema.propertiesChildren { nextNode, ok := castCurrentNode[pSchema.property] if ok { - subContext := newJsonContext(pSchema.property, context) + subContext := NewJsonContext(pSchema.property, context) v.validateRecursive(pSchema, nextNode, result, subContext) } } @@ -212,7 +216,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i case reflect.Bool: if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_BOOLEAN) { - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -234,7 +238,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i case reflect.String: if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_STRING) { - result.addError( + result.addInternalError( new(InvalidTypeError), context, currentNode, @@ -263,7 +267,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i } // Different kinds of validation there, subSchema / common / array / object / string... -func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *JsonContext) { if internalLogEnabled { internalLog("validateSchema %s", context.String()) @@ -287,7 +291,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte } if !validatedAnyOf { - result.addError(new(NumberAnyOfError), context, currentNode, ErrorDetails{}) + result.addInternalError(new(NumberAnyOfError), context, currentNode, ErrorDetails{}) if bestValidationResult != nil { // add error messages of closest matching subSchema as @@ -313,7 +317,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte if nbValidated != 1 { - result.addError(new(NumberOneOfError), context, currentNode, ErrorDetails{}) + result.addInternalError(new(NumberOneOfError), context, currentNode, ErrorDetails{}) if nbValidated == 0 { // add error messages of closest matching subSchema as @@ -336,14 +340,14 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte } if nbValidated != len(currentSubSchema.allOf) { - result.addError(new(NumberAllOfError), context, currentNode, ErrorDetails{}) + result.addInternalError(new(NumberAllOfError), context, currentNode, ErrorDetails{}) } } if currentSubSchema.not != nil { validationResult := currentSubSchema.not.subValidateWithContext(currentNode, context) if validationResult.Valid() { - result.addError(new(NumberNotError), context, currentNode, ErrorDetails{}) + result.addInternalError(new(NumberNotError), context, currentNode, ErrorDetails{}) } } @@ -356,7 +360,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte case []string: for _, dependOnKey := range dependency { if _, dependencyResolved := currentNode.(map[string]interface{})[dependOnKey]; !dependencyResolved { - result.addError( + result.addInternalError( new(MissingDependencyError), context, currentNode, @@ -367,31 +371,65 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte case *subSchema: dependency.validateRecursive(dependency, currentNode, result, context) - } } } } } + if currentSubSchema._if != nil { + validationResultIf := currentSubSchema._if.subValidateWithContext(currentNode, context) + if currentSubSchema._then != nil && validationResultIf.Valid() { + validationResultThen := currentSubSchema._then.subValidateWithContext(currentNode, context) + if !validationResultThen.Valid() { + result.addInternalError(new(ConditionThenError), context, currentNode, ErrorDetails{}) + result.mergeErrors(validationResultThen) + } + } + if currentSubSchema._else != nil && !validationResultIf.Valid() { + validationResultElse := currentSubSchema._else.subValidateWithContext(currentNode, context) + if !validationResultElse.Valid() { + result.addInternalError(new(ConditionElseError), context, currentNode, ErrorDetails{}) + result.mergeErrors(validationResultElse) + } + } + } + result.incrementScore() } -func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) { if internalLogEnabled { internalLog("validateCommon %s", context.String()) internalLog(" %v", value) } + // const: + if currentSubSchema._const != nil { + vString, err := marshalWithoutNumber(value) + if err != nil { + result.addInternalError(new(InternalError), context, value, ErrorDetails{"error": err}) + } + if *vString != *currentSubSchema._const { + result.addInternalError(new(ConstError), + context, + value, + ErrorDetails{ + "allowed": *currentSubSchema._const, + }, + ) + } + } + // enum: if len(currentSubSchema.enum) > 0 { has, err := currentSubSchema.ContainsEnum(value) if err != nil { - result.addError(new(InternalError), context, value, ErrorDetails{"error": err}) + result.addInternalError(new(InternalError), context, value, ErrorDetails{"error": err}) } if !has { - result.addError( + result.addInternalError( new(EnumError), context, value, @@ -405,7 +443,7 @@ func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{ result.incrementScore() } -func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface{}, result *Result, context *JsonContext) { if internalLogEnabled { internalLog("validateArray %s", context.String()) @@ -417,7 +455,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface // TODO explain if currentSubSchema.itemsChildrenIsSingleSchema { for i := range value { - subContext := newJsonContext(strconv.Itoa(i), context) + subContext := NewJsonContext(strconv.Itoa(i), context) validationResult := currentSubSchema.itemsChildren[0].subValidateWithContext(value[i], subContext) result.mergeErrors(validationResult) } @@ -428,7 +466,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface // while we have both schemas and values, check them against each other for i := 0; i != nbItems && i != nbValues; i++ { - subContext := newJsonContext(strconv.Itoa(i), context) + subContext := NewJsonContext(strconv.Itoa(i), context) validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext) result.mergeErrors(validationResult) } @@ -440,12 +478,12 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface switch currentSubSchema.additionalItems.(type) { case bool: if !currentSubSchema.additionalItems.(bool) { - result.addError(new(ArrayNoAdditionalItemsError), context, value, ErrorDetails{}) + result.addInternalError(new(ArrayNoAdditionalItemsError), context, value, ErrorDetails{}) } case *subSchema: additionalItemSchema := currentSubSchema.additionalItems.(*subSchema) for i := nbItems; i != nbValues; i++ { - subContext := newJsonContext(strconv.Itoa(i), context) + subContext := NewJsonContext(strconv.Itoa(i), context) validationResult := additionalItemSchema.subValidateWithContext(value[i], subContext) result.mergeErrors(validationResult) } @@ -457,7 +495,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface // minItems & maxItems if currentSubSchema.minItems != nil { if nbValues < int(*currentSubSchema.minItems) { - result.addError( + result.addInternalError( new(ArrayMinItemsError), context, value, @@ -467,7 +505,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface } if currentSubSchema.maxItems != nil { if nbValues > int(*currentSubSchema.maxItems) { - result.addError( + result.addInternalError( new(ArrayMaxItemsError), context, value, @@ -480,12 +518,12 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface if currentSubSchema.uniqueItems { var stringifiedItems []string for _, v := range value { - vString, err := marshalToJsonString(v) + vString, err := marshalWithoutNumber(v) if err != nil { - result.addError(new(InternalError), context, value, ErrorDetails{"err": err}) + result.addInternalError(new(InternalError), context, value, ErrorDetails{"err": err}) } if isStringInSlice(stringifiedItems, *vString) { - result.addError( + result.addInternalError( new(ItemsMustBeUniqueError), context, value, @@ -496,10 +534,42 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface } } + // contains: + + if currentSubSchema.contains != nil { + validatedOne := false + var bestValidationResult *Result + + for i, v := range value { + subContext := NewJsonContext(strconv.Itoa(i), context) + + validationResult := currentSubSchema.contains.subValidateWithContext(v, subContext) + if validationResult.Valid() { + validatedOne = true + break + } else { + if bestValidationResult == nil || validationResult.score > bestValidationResult.score { + bestValidationResult = validationResult + } + } + } + if !validatedOne { + result.addInternalError( + new(ArrayContainsError), + context, + value, + ErrorDetails{}, + ) + if bestValidationResult != nil { + result.mergeErrors(bestValidationResult) + } + } + } + result.incrementScore() } -func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string]interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string]interface{}, result *Result, context *JsonContext) { if internalLogEnabled { internalLog("validateObject %s", context.String()) @@ -509,7 +579,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string // minProperties & maxProperties: if currentSubSchema.minProperties != nil { if len(value) < int(*currentSubSchema.minProperties) { - result.addError( + result.addInternalError( new(ArrayMinPropertiesError), context, value, @@ -519,7 +589,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string } if currentSubSchema.maxProperties != nil { if len(value) > int(*currentSubSchema.maxProperties) { - result.addError( + result.addInternalError( new(ArrayMaxPropertiesError), context, value, @@ -534,7 +604,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string if ok { result.incrementScore() } else { - result.addError( + result.addInternalError( new(RequiredError), context, value, @@ -565,7 +635,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string if found { if pp_has && !pp_match { - result.addError( + result.addInternalError( new(AdditionalPropertyNotAllowedError), context, value[pk], @@ -576,7 +646,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string } else { if !pp_has || !pp_match { - result.addError( + result.addInternalError( new(AdditionalPropertyNotAllowedError), context, value[pk], @@ -628,7 +698,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string if pp_has && !pp_match { - result.addError( + result.addInternalError( new(InvalidPropertyPatternError), context, value[pk], @@ -642,10 +712,25 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string } } + // propertyNames: + if currentSubSchema.propertyNames != nil { + for pk := range value { + validationResult := currentSubSchema.propertyNames.subValidateWithContext(pk, context) + if !validationResult.Valid() { + result.addInternalError(new(InvalidPropertyNameError), + context, + value, ErrorDetails{ + "property": pk, + }) + result.mergeErrors(validationResult) + } + } + } + result.incrementScore() } -func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *jsonContext) (has bool, matched bool) { +func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) (has bool, matched bool) { if internalLogEnabled { internalLog("validatePatternProperty %s", context.String()) @@ -659,12 +744,10 @@ func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key str for pk, pv := range currentSubSchema.patternProperties { if matches, _ := regexp.MatchString(pk, key); matches { has = true - subContext := newJsonContext(key, context) + subContext := NewJsonContext(key, context) validationResult := pv.subValidateWithContext(value, subContext) result.mergeErrors(validationResult) - if validationResult.Valid() { - validatedkey = true - } + validatedkey = true } } @@ -677,7 +760,7 @@ func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key str return has, true } -func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) { // Ignore JSON numbers if isJsonNumber(value) { @@ -699,7 +782,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{ // minLength & maxLength: if currentSubSchema.minLength != nil { if utf8.RuneCount([]byte(stringValue)) < int(*currentSubSchema.minLength) { - result.addError( + result.addInternalError( new(StringLengthGTEError), context, value, @@ -709,7 +792,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{ } if currentSubSchema.maxLength != nil { if utf8.RuneCount([]byte(stringValue)) > int(*currentSubSchema.maxLength) { - result.addError( + result.addInternalError( new(StringLengthLTEError), context, value, @@ -721,7 +804,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{ // pattern: if currentSubSchema.pattern != nil { if !currentSubSchema.pattern.MatchString(stringValue) { - result.addError( + result.addInternalError( new(DoesNotMatchPatternError), context, value, @@ -734,7 +817,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{ // format if currentSubSchema.format != "" { if !FormatCheckers.IsFormat(currentSubSchema.format, stringValue) { - result.addError( + result.addInternalError( new(DoesNotMatchFormatError), context, value, @@ -746,7 +829,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{ result.incrementScore() } -func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) { +func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) { // Ignore non numbers if !isJsonNumber(value) { @@ -759,17 +842,17 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{ } number := value.(json.Number) - float64Value, _ := number.Float64() + float64Value, _ := new(big.Float).SetString(string(number)) // multipleOf: if currentSubSchema.multipleOf != nil { - if !isFloat64AnInteger(float64Value / *currentSubSchema.multipleOf) { - result.addError( + if q := new(big.Float).Quo(float64Value, currentSubSchema.multipleOf); !q.IsInt() { + result.addInternalError( new(MultipleOfError), context, resultErrorFormatJsonNumber(number), - ErrorDetails{"multiple": *currentSubSchema.multipleOf}, + ErrorDetails{"multiple": currentSubSchema.multipleOf}, ) } } @@ -777,24 +860,24 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{ //maximum & exclusiveMaximum: if currentSubSchema.maximum != nil { if currentSubSchema.exclusiveMaximum { - if float64Value >= *currentSubSchema.maximum { - result.addError( + if float64Value.Cmp(currentSubSchema.maximum) >= 0 { + result.addInternalError( new(NumberLTError), context, resultErrorFormatJsonNumber(number), ErrorDetails{ - "max": resultErrorFormatNumber(*currentSubSchema.maximum), + "max": currentSubSchema.maximum, }, ) } } else { - if float64Value > *currentSubSchema.maximum { - result.addError( + if float64Value.Cmp(currentSubSchema.maximum) == 1 { + result.addInternalError( new(NumberLTEError), context, resultErrorFormatJsonNumber(number), ErrorDetails{ - "max": resultErrorFormatNumber(*currentSubSchema.maximum), + "max": currentSubSchema.maximum, }, ) } @@ -804,24 +887,25 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{ //minimum & exclusiveMinimum: if currentSubSchema.minimum != nil { if currentSubSchema.exclusiveMinimum { - if float64Value <= *currentSubSchema.minimum { - result.addError( + if float64Value.Cmp(currentSubSchema.minimum) <= 0 { + // if float64Value <= *currentSubSchema.minimum { + result.addInternalError( new(NumberGTError), context, resultErrorFormatJsonNumber(number), ErrorDetails{ - "min": resultErrorFormatNumber(*currentSubSchema.minimum), + "min": currentSubSchema.minimum, }, ) } } else { - if float64Value < *currentSubSchema.minimum { - result.addError( + if float64Value.Cmp(currentSubSchema.minimum) == -1 { + result.addInternalError( new(NumberGTEError), context, resultErrorFormatJsonNumber(number), ErrorDetails{ - "min": resultErrorFormatNumber(*currentSubSchema.minimum), + "min": currentSubSchema.minimum, }, ) } @@ -831,7 +915,7 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{ // format if currentSubSchema.format != "" { if !FormatCheckers.IsFormat(currentSubSchema.format, float64Value) { - result.addError( + result.addInternalError( new(DoesNotMatchFormatError), context, value, diff --git a/vendor/github.com/yalp/jsonpath/.travis.yml b/vendor/github.com/yalp/jsonpath/.travis.yml new file mode 100644 index 0000000..8b3da87 --- /dev/null +++ b/vendor/github.com/yalp/jsonpath/.travis.yml @@ -0,0 +1,3 @@ +language: go +go: + - "1.10" diff --git a/vendor/github.com/yalp/jsonpath/LICENSE b/vendor/github.com/yalp/jsonpath/LICENSE new file mode 100644 index 0000000..190a34f --- /dev/null +++ b/vendor/github.com/yalp/jsonpath/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2015, Marc Capdevielle +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/yalp/jsonpath/README.md b/vendor/github.com/yalp/jsonpath/README.md index 2788ba1..3af6b4b 100644 --- a/vendor/github.com/yalp/jsonpath/README.md +++ b/vendor/github.com/yalp/jsonpath/README.md @@ -1,3 +1,8 @@ +[![Build Status](https://travis-ci.org/yalp/jsonpath.svg?branch=master)](https://travis-ci.org/yalp/jsonpath) + +This was mostly an experiment to learn go and test using closures to interpret a JSON path. +You should use https://github.com/PaesslerAG/jsonpath instead. + # jsonpath a (partial) implementation in [Go](http://golang.org) based on [Stefan Goener JSON Path](http://goessner.net/articles/JsonPath/) diff --git a/vendor/github.com/yalp/jsonpath/jsonpath.go b/vendor/github.com/yalp/jsonpath/jsonpath.go index ebb6018..75bb666 100644 --- a/vendor/github.com/yalp/jsonpath/jsonpath.go +++ b/vendor/github.com/yalp/jsonpath/jsonpath.go @@ -29,6 +29,7 @@ package jsonpath import ( "errors" "fmt" + "sort" "strconv" "strings" "text/scanner" @@ -65,7 +66,7 @@ type FilterFunc func(value interface{}) (interface{}, error) // a: the list of actions to apply next // v: value -// actionFunc applies a transformation to current value (possibily using root) +// actionFunc applies a transformation to current value (possibility using root) // then applies the next action from actions (using next()) to the output of the transformation type actionFunc func(r, c interface{}, a actions) (interface{}, error) @@ -84,6 +85,15 @@ func (a actions) call(r, c interface{}) (interface{}, error) { type exprFunc func(r, c interface{}) (interface{}, error) +type searchResults []interface{} + +func (sr searchResults) append(v interface{}) searchResults { + if vsr, ok := v.(searchResults); ok { + return append(sr, vsr...) + } + return append(sr, v) +} + type parser struct { scanner scanner.Scanner path string @@ -93,7 +103,13 @@ type parser struct { func (p *parser) prepareFilterFunc() FilterFunc { actions := p.actions return func(value interface{}) (interface{}, error) { - return actions.next(value, value) + result, err := actions.next(value, value) + if err == nil { + if sr, ok := result.(searchResults); ok { + result = ([]interface{})(sr) + } + } + return result, err } } @@ -151,7 +167,7 @@ func (p *parser) parsePath() (err error) { p.add(func(r, c interface{}, a actions) (interface{}, error) { return c, nil }) return nil default: - err = fmt.Errorf("unexcepted token %s at %d", p.text(), p.column()) + err = fmt.Errorf("unexpected token %s at %d", p.text(), p.column()) } } return @@ -175,14 +191,14 @@ func (p *parser) parseObjAccess() error { func (p *parser) prepareWildcard() error { p.add(func(r, c interface{}, a actions) (interface{}, error) { - values := []interface{}{} + values := searchResults{} if obj, ok := c.(map[string]interface{}); ok { - for _, v := range obj { + for _, v := range valuesSortedByKey(obj) { v, err := a.next(r, v) if err != nil { continue } - values = append(values, v) + values = values.append(v) } } else if array, ok := c.([]interface{}); ok { for _, v := range array { @@ -190,7 +206,7 @@ func (p *parser) prepareWildcard() error { if err != nil { continue } - values = append(values, v) + values = values.append(v) } } return values, nil @@ -199,22 +215,31 @@ func (p *parser) prepareWildcard() error { } func (p *parser) parseDeep() (err error) { - p.add(func(r, c interface{}, a actions) (interface{}, error) { - return recSearch(r, c, a, []interface{}{}), nil - }) p.scanner.Mode = scanner.ScanIdents switch p.scan() { case scanner.Ident: + p.add(func(r, c interface{}, a actions) (interface{}, error) { + return recSearchParent(r, c, a, searchResults{}), nil + }) return p.parseObjAccess() - case '*': - p.add(func(r, c interface{}, a actions) (interface{}, error) { return a.next(r, c) }) - return nil case '[': + p.add(func(r, c interface{}, a actions) (interface{}, error) { + return recSearchParent(r, c, a, searchResults{}), nil + }) return p.parseBracket() + case '*': + p.add(func(r, c interface{}, a actions) (interface{}, error) { + return recSearchChildren(r, c, a, searchResults{}), nil + }) + p.add(func(r, c interface{}, a actions) (interface{}, error) { + return a.next(r, c) + }) + return nil case scanner.EOF: return fmt.Errorf("cannot end with a scan '..' at %d", p.column()) default: - return fmt.Errorf("unexpected token '%s' after deep search '..' at %d", p.text(), p.column()) + return fmt.Errorf("unexpected token '%s' after deep search '..' at %d", + p.text(), p.column()) } } @@ -272,7 +297,7 @@ parse: return err } indexes = append(indexes, filter) - case ':': // when slice value is ommited + case ':': // when slice value is omitted if mode == "" { mode = "slice" indexes = append(indexes, 0) @@ -282,7 +307,7 @@ parse: return fmt.Errorf("unexpected ':' after %s at %d", mode, p.column()) } continue // skip separator parsing, it's done - case ']': // when slice value is ommited + case ']': // when slice value is omitted if mode == "slice" { indexes = append(indexes, 0) } else if len(indexes) == 0 { @@ -337,20 +362,21 @@ func (p *parser) parseExpression() (exprFunc, error) { return nil, errors.New("Expression are not (yet) implemented") } -func recSearch(r, c interface{}, a actions, acc []interface{}) []interface{} { +func recSearchParent(r, c interface{}, a actions, acc searchResults) searchResults { + if v, err := a.next(r, c); err == nil { + acc = acc.append(v) + } + return recSearchChildren(r, c, a, acc) +} + +func recSearchChildren(r, c interface{}, a actions, acc searchResults) searchResults { if obj, ok := c.(map[string]interface{}); ok { - for _, c := range obj { - if result, err := a.next(r, c); err == nil { - acc = append(acc, result) - } - acc = recSearch(r, c, a, acc) + for _, c := range valuesSortedByKey(obj) { + acc = recSearchParent(r, c, a, acc) } } else if array, ok := c.([]interface{}); ok { for _, c := range array { - if result, err := a.next(r, c); err == nil { - acc = append(acc, result) - } - acc = recSearch(r, c, a, acc) + acc = recSearchParent(r, c, a, acc) } } return acc @@ -413,14 +439,22 @@ func prepareSlice(indexes []interface{}, column int) actionFunc { if step == 0 { step = 1 } - var values []interface{} + var values searchResults if step > 0 { for i := start; i < end; i += step { - values = append(values, array[i]) + v, err := a.next(r, array[i]) + if err != nil { + continue + } + values = values.append(v) } } else { // reverse order on negative step for i := end - 1; i >= start; i += step { - values = append(values, array[i]) + v, err := a.next(r, array[i]) + if err != nil { + continue + } + values = values.append(v) } } return values, nil @@ -430,7 +464,7 @@ func prepareSlice(indexes []interface{}, column int) actionFunc { func prepareUnion(indexes []interface{}, column int) actionFunc { return func(r, c interface{}, a actions) (interface{}, error) { if obj, ok := c.(map[string]interface{}); ok { - var values []interface{} + var values searchResults for _, index := range indexes { key, err := indexAsString(index, r, c) if err != nil { @@ -442,11 +476,11 @@ func prepareUnion(indexes []interface{}, column int) actionFunc { if c, err = a.next(r, c); err != nil { return nil, err } - values = append(values, c) + values = values.append(c) } return values, nil } else if array, ok := c.([]interface{}); ok { - var values []interface{} + var values searchResults for _, index := range indexes { index, err := indexAsInt(index, r, c) if err != nil { @@ -458,7 +492,7 @@ func prepareUnion(indexes []interface{}, column int) actionFunc { if c, err = a.next(r, array[index]); err != nil { return nil, err } - values = append(values, c) + values = values.append(c) } return values, nil } @@ -517,3 +551,19 @@ func indexAsString(key, r, c interface{}) (string, error) { return "", fmt.Errorf("expected key value (string or expression returning a string) for object access") } } + +func valuesSortedByKey(m map[string]interface{}) []interface{} { + if len(m) == 0 { + return nil + } + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + values := make([]interface{}, 0, len(m)) + for _, k := range keys { + values = append(values, m[k]) + } + return values +} diff --git a/vendor/github.com/yalp/jsonpath/jsonpath_test.go b/vendor/github.com/yalp/jsonpath/jsonpath_test.go index cb40fca..83ad090 100644 --- a/vendor/github.com/yalp/jsonpath/jsonpath_test.go +++ b/vendor/github.com/yalp/jsonpath/jsonpath_test.go @@ -59,12 +59,41 @@ var sample = map[string]interface{}{ "D": map[string]interface{}{ "C": 3.1415, "V": []interface{}{ - "string2", + "string2a", + "string2b", map[string]interface{}{ "C": 3.141592, }, }, }, + "E": map[string]interface{}{ + "A": []interface{}{"string3"}, + "D": map[string]interface{}{ + "V": map[string]interface{}{ + "C": 3.14159265, + }, + }, + }, + "F": map[string]interface{}{ + "V": []interface{}{ + "string4a", + "string4b", + map[string]interface{}{ + "CC": 3.1415926535, + }, + map[string]interface{}{ + "CC": "hello", + }, + []interface{}{ + "string5a", + "string5b", + }, + []interface{}{ + "string6a", + "string6b", + }, + }, + }, } func TestGossner(t *testing.T) { @@ -79,52 +108,131 @@ func TestGossner(t *testing.T) { } func TestParsing(t *testing.T) { + t.Run("pick", func(t *testing.T) { + assert(t, sample, map[string]interface{}{ + "$": sample, + "$.A[0]": "string", + `$["A"][0]`: "string", + "$.A": []interface{}{"string", 23.3, 3, true, false, nil}, + "$.A[*]": []interface{}{"string", 23.3, 3, true, false, nil}, + "$.A.*": []interface{}{"string", 23.3, 3, true, false, nil}, + "$.A.*.a": []interface{}{}, + }) + }) - tests := map[string]interface{}{ - "$": sample, - "$.A[0]": "string", - `$["A"][0]`: "string", - `$[A][0]`: "string", - "$.A": []interface{}{"string", 23.3, 3, true, false, nil}, - "$.A[*]": []interface{}{"string", 23.3, 3, true, false, nil}, - "$.A.*": []interface{}{"string", 23.3, 3, true, false, nil}, - "$.A.*.a": []interface{}{}, - "$.*.V[0]": []interface{}{"string2"}, - "$[B,C]": []interface{}{"value", 3.14}, - "$.A[1,4,2]": []interface{}{23.3, false, 3}, - "$[C,B]": []interface{}{3.14, "value"}, - "$.A[1:4]": []interface{}{23.3, 3, true}, - "$.A[::2]": []interface{}{"string", 3, false}, - "$.A[-2:]": []interface{}{false, nil}, - "$.A[:-1]": []interface{}{"string", 23.3, 3, true, false}, - "$.A[::-1]": []interface{}{nil, false, true, 3, 23.3, "string"}, - "$..C": []interface{}{3.1415, 3.141592}, - "$..V[1].C": []interface{}{3.141592}, - "$..[C]": []interface{}{3.1415, 3.141592}, - "$.D.V..*": []interface{}{ - "string2", - map[string]interface{}{ - "C": 3.141592, + t.Run("slice", func(t *testing.T) { + assert(t, sample, map[string]interface{}{ + "$.A[1,4,2]": []interface{}{23.3, false, 3}, + `$["B","C"]`: []interface{}{"value", 3.14}, + `$["C","B"]`: []interface{}{3.14, "value"}, + "$.A[1:4]": []interface{}{23.3, 3, true}, + "$.A[::2]": []interface{}{"string", 3, false}, + "$.A[-2:]": []interface{}{false, nil}, + "$.A[:-1]": []interface{}{"string", 23.3, 3, true, false}, + "$.A[::-1]": []interface{}{nil, false, true, 3, 23.3, "string"}, + "$.F.V[4:5][0,1]": []interface{}{"string5a", "string5b"}, + "$.F.V[4:6][1]": []interface{}{"string5b", "string6b"}, + "$.F.V[4:6][0,1]": []interface{}{"string5a", "string5b", "string6a", "string6b"}, + "$.F.V[4,5][0:2]": []interface{}{"string5a", "string5b", "string6a", "string6b"}, + "$.F.V[4:6]": []interface{}{ + []interface{}{ + "string5a", + "string5b", + }, + []interface{}{ + "string6a", + "string6b", + }, }, - 3.141592, - }, - "$..[0]": []interface{}{"string", "string2"}, - "$..ZZ": []interface{}{}, - } - assert(t, sample, tests) + }) + }) + + t.Run("quote", func(t *testing.T) { + assert(t, sample, map[string]interface{}{ + `$[A][0]`: "string", + `$["A"][0]`: "string", + `$[B,C]`: []interface{}{"value", 3.14}, + `$["B","C"]`: []interface{}{"value", 3.14}, + }) + }) + + t.Run("search", func(t *testing.T) { + assert(t, sample, map[string]interface{}{ + "$..C": []interface{}{3.14, 3.1415, 3.141592, 3.14159265}, + `$..["C"]`: []interface{}{3.14, 3.1415, 3.141592, 3.14159265}, + "$.D.V..C": []interface{}{3.141592}, + "$.D.V.*.C": []interface{}{3.141592}, + "$.D.V..*.C": []interface{}{3.141592}, + "$.D.*..C": []interface{}{3.141592}, + "$.*.V..C": []interface{}{3.141592}, + "$.*.D.V.C": []interface{}{3.14159265}, + "$.*.D..C": []interface{}{3.14159265}, + "$.*.D.V..*": []interface{}{3.14159265}, + "$..D..V..C": []interface{}{3.141592, 3.14159265}, + "$.*.*.*.C": []interface{}{3.141592, 3.14159265}, + "$..V..C": []interface{}{3.141592, 3.14159265}, + "$.D.V..*": []interface{}{ + "string2a", + "string2b", + map[string]interface{}{ + "C": 3.141592, + }, + 3.141592, + }, + "$..A": []interface{}{ + []interface{}{"string", 23.3, 3, true, false, nil}, + []interface{}{"string3"}, + }, + "$..A..*": []interface{}{"string", 23.3, 3, true, false, nil, "string3"}, + "$.A..*": []interface{}{"string", 23.3, 3, true, false, nil}, + "$.A.*": []interface{}{"string", 23.3, 3, true, false, nil}, + "$..A[0,1]": []interface{}{"string", 23.3}, + "$..A[0]": []interface{}{"string", "string3"}, + "$.*.V[0]": []interface{}{"string2a", "string4a"}, + "$.*.V[1]": []interface{}{"string2b", "string4b"}, + "$.*.V[0,1]": []interface{}{"string2a", "string2b", "string4a", "string4b"}, + "$.*.V[0:2]": []interface{}{"string2a", "string2b", "string4a", "string4b"}, + "$.*.V[2].C": []interface{}{3.141592}, + "$..V[2].C": []interface{}{3.141592}, + "$..V[*].C": []interface{}{3.141592}, + "$.*.V[2].*": []interface{}{3.141592, 3.1415926535}, + "$.*.V[2:3].*": []interface{}{3.141592, 3.1415926535}, + "$.*.V[2:4].*": []interface{}{3.141592, 3.1415926535, "hello"}, + "$..V[2,3].CC": []interface{}{3.1415926535, "hello"}, + "$..V[2:4].CC": []interface{}{3.1415926535, "hello"}, + "$..V[*].*": []interface{}{ + 3.141592, + 3.1415926535, + "hello", + "string5a", + "string5b", + "string6a", + "string6b", + }, + "$..[0]": []interface{}{ + "string", + "string2a", + "string3", + "string4a", + "string5a", + "string6a", + }, + "$..ZZ": []interface{}{}, + }) + }) } func TestErrors(t *testing.T) { tests := map[string]string{ ".A": "path must start with a '$'", "$.": "expected JSON child identifier after '.'", - "$.1": "unexcepted token .1", + "$.1": "unexpected token .1", "$.A[]": "expected at least one key, index or expression", `$["]`: "bad string invalid syntax", `$[A][0`: "unexpected end of path", "$.ZZZ": "child 'ZZZ' not found in JSON object", - "$.A*]": "unexcepted token *", - "$.*V": "unexcepted token V", + "$.A*]": "unexpected token *", + "$.*V": "unexpected token V", "$[B,C": "unexpected end of path", "$.A[1,4.2]": "unexpected token '.'", "$[C:B]": "expected JSON array", diff --git a/vendor/golang.org/x/crypto/CONTRIBUTING.md b/vendor/golang.org/x/crypto/CONTRIBUTING.md index 88dff59..d0485e8 100644 --- a/vendor/golang.org/x/crypto/CONTRIBUTING.md +++ b/vendor/golang.org/x/crypto/CONTRIBUTING.md @@ -4,16 +4,15 @@ Go is an open source project. It is the work of hundreds of contributors. We appreciate your help! - ## Filing issues When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. @@ -23,9 +22,5 @@ The gophers there will answer or ask you to file an issue if you've tripped over Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go index fa9c4b3..7df6476 100644 --- a/vendor/golang.org/x/crypto/acme/acme.go +++ b/vendor/golang.org/x/crypto/acme/acme.go @@ -14,7 +14,6 @@ package acme import ( - "bytes" "context" "crypto" "crypto/ecdsa" @@ -23,6 +22,8 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/hex" "encoding/json" @@ -33,14 +34,26 @@ import ( "io/ioutil" "math/big" "net/http" - "strconv" "strings" "sync" "time" ) -// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. -const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" +const ( + // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. + LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" + + // ALPNProto is the ALPN protocol name used by a CA server when validating + // tls-alpn-01 challenges. + // + // Package users must ensure their servers can negotiate the ACME ALPN in + // order for tls-alpn-01 challenge verifications to succeed. + // See the crypto/tls package's Config.NextProtos field. + ALPNProto = "acme-tls/1" +) + +// idPeACMEIdentifierV1 is the OID for the ACME extension for the TLS-ALPN challenge. +var idPeACMEIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1} const ( maxChainLen = 5 // max depth and breadth of a certificate chain @@ -76,6 +89,22 @@ type Client struct { // will have no effect. DirectoryURL string + // RetryBackoff computes the duration after which the nth retry of a failed request + // should occur. The value of n for the first call on failure is 1. + // The values of r and resp are the request and response of the last failed attempt. + // If the returned value is negative or zero, no more retries are done and an error + // is returned to the caller of the original method. + // + // Requests which result in a 4xx client error are not retried, + // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. + // + // If RetryBackoff is nil, a truncated exponential backoff algorithm + // with the ceiling of 10 seconds is used, where each subsequent retry n + // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), + // preferring the former if "Retry-After" header is found in the resp. + // The jitter is a random value up to 1 second. + RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration + dirMu sync.Mutex // guards writes to dir dir *Directory // cached result of Client's Discover method @@ -99,15 +128,12 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) { if dirURL == "" { dirURL = LetsEncryptURL } - res, err := c.get(ctx, dirURL) + res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK)) if err != nil { return Directory{}, err } defer res.Body.Close() c.addNonce(res.Header) - if res.StatusCode != http.StatusOK { - return Directory{}, responseError(res) - } var v struct { Reg string `json:"new-reg"` @@ -166,14 +192,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, req.NotAfter = now.Add(exp).Format(time.RFC3339) } - res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req) + res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated)) if err != nil { return nil, "", err } defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - return nil, "", responseError(res) - } curl := res.Header.Get("Location") // cert permanent URL if res.ContentLength == 0 { @@ -196,26 +219,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, // Callers are encouraged to parse the returned value to ensure the certificate is valid // and has expected features. func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { - for { - res, err := c.get(ctx, url) - if err != nil { - return nil, err - } - defer res.Body.Close() - if res.StatusCode == http.StatusOK { - return c.responseCert(ctx, res, bundle) - } - if res.StatusCode > 299 { - return nil, responseError(res) - } - d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second) - select { - case <-time.After(d): - // retry - case <-ctx.Done(): - return nil, ctx.Err() - } + res, err := c.get(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err } + return c.responseCert(ctx, res, bundle) } // RevokeCert revokes a previously issued certificate cert, provided in DER format. @@ -241,14 +249,11 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, if key == nil { key = c.Key } - res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body) + res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK)) if err != nil { return err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return responseError(res) - } return nil } @@ -329,14 +334,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, Resource: "new-authz", Identifier: authzID{Type: "dns", Value: domain}, } - res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req) + res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - return nil, responseError(res) - } var v wireAuthz if err := json.NewDecoder(res.Body).Decode(&v); err != nil { @@ -353,14 +355,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, // If a caller needs to poll an authorization until its status is final, // see the WaitAuthorization method. func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } var v wireAuthz if err := json.NewDecoder(res.Body).Decode(&v); err != nil { return nil, fmt.Errorf("acme: invalid response: %v", err) @@ -387,56 +386,58 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { Status: "deactivated", Delete: true, } - res, err := c.retryPostJWS(ctx, c.Key, url, req) + res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK)) if err != nil { return err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return responseError(res) - } return nil } // WaitAuthorization polls an authorization at the given URL // until it is in one of the final states, StatusValid or StatusInvalid, -// or the context is done. +// the ACME CA responded with a 4xx error code, or the context is done. // // It returns a non-nil Authorization only if its Status is StatusValid. // In all other cases WaitAuthorization returns an error. // If the Status is StatusInvalid, the returned error is of type *AuthorizationError. func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { - sleep := sleeper(ctx) for { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } - retry := res.Header.Get("Retry-After") - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - res.Body.Close() - if err := sleep(retry, 1); err != nil { - return nil, err - } - continue - } + var raw wireAuthz err = json.NewDecoder(res.Body).Decode(&raw) res.Body.Close() - if err != nil { - if err := sleep(retry, 0); err != nil { - return nil, err - } - continue - } - if raw.Status == StatusValid { + switch { + case err != nil: + // Skip and retry. + case raw.Status == StatusValid: return raw.authorization(url), nil - } - if raw.Status == StatusInvalid { + case raw.Status == StatusInvalid: return nil, raw.error(url) } - if err := sleep(retry, 0); err != nil { - return nil, err + + // Exponential backoff is implemented in c.get above. + // This is just to prevent continuously hitting the CA + // while waiting for a final authorization status. + d := retryAfter(res.Header.Get("Retry-After")) + if d == 0 { + // Given that the fastest challenges TLS-SNI and HTTP-01 + // require a CA to make at least 1 network round trip + // and most likely persist a challenge state, + // this default delay seems reasonable. + d = time.Second + } + t := time.NewTimer(d) + select { + case <-ctx.Done(): + t.Stop() + return nil, ctx.Err() + case <-t.C: + // Retry. } } } @@ -445,14 +446,11 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat // // A client typically polls a challenge status using this method. func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } v := wireChallenge{URI: url} if err := json.NewDecoder(res.Body).Decode(&v); err != nil { return nil, fmt.Errorf("acme: invalid response: %v", err) @@ -479,16 +477,14 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error Type: chal.Type, Auth: auth, } - res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req) + res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus( + http.StatusOK, // according to the spec + http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) + )) if err != nil { return nil, err } defer res.Body.Close() - // Note: the protocol specifies 200 as the expected response code, but - // letsencrypt seems to be returning 202. - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } var v wireChallenge if err := json.NewDecoder(res.Body).Decode(&v); err != nil { @@ -545,7 +541,7 @@ func (c *Client) HTTP01ChallengePath(token string) string { // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. // // The returned certificate is valid for the next 24 hours and must be presented only when -// the server name of the client hello matches exactly the returned name value. +// the server name of the TLS ClientHello matches exactly the returned name value. func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { ka, err := keyAuth(c.Key.Public(), token) if err != nil { @@ -572,7 +568,7 @@ func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tl // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. // // The returned certificate is valid for the next 24 hours and must be presented only when -// the server name in the client hello matches exactly the returned name value. +// the server name in the TLS ClientHello matches exactly the returned name value. func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { b := sha256.Sum256([]byte(token)) h := hex.EncodeToString(b[:]) @@ -593,6 +589,52 @@ func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tl return cert, sanA, nil } +// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. +// Servers can present the certificate to validate the challenge and prove control +// over a domain name. For more details on TLS-ALPN-01 see +// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3 +// +// The token argument is a Challenge.Token value. +// If a WithKey option is provided, its private part signs the returned cert, +// and the public part is used to specify the signee. +// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// +// The returned certificate is valid for the next 24 hours and must be presented only when +// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol +// has been specified. +func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) { + ka, err := keyAuth(c.Key.Public(), token) + if err != nil { + return tls.Certificate{}, err + } + shasum := sha256.Sum256([]byte(ka)) + extValue, err := asn1.Marshal(shasum[:]) + if err != nil { + return tls.Certificate{}, err + } + acmeExtension := pkix.Extension{ + Id: idPeACMEIdentifierV1, + Critical: true, + Value: extValue, + } + + tmpl := defaultTLSChallengeCertTemplate() + + var newOpt []CertOption + for _, o := range opt { + switch o := o.(type) { + case *certOptTemplate: + t := *(*x509.Certificate)(o) // shallow copy is ok + tmpl = &t + default: + newOpt = append(newOpt, o) + } + } + tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) + newOpt = append(newOpt, WithTemplate(tmpl)) + return tlsChallengeCert([]string{domain}, newOpt) +} + // doReg sends all types of registration requests. // The type of request is identified by typ argument, which is a "resource" // in the ACME spec terms. @@ -612,14 +654,15 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun req.Contact = acct.Contact req.Agreement = acct.AgreedTerms } - res, err := c.retryPostJWS(ctx, c.Key, url, req) + res, err := c.post(ctx, c.Key, url, req, wantStatus( + http.StatusOK, // updates and deletes + http.StatusCreated, // new account creation + http.StatusAccepted, // Let's Encrypt divergent implementation + )) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode < 200 || res.StatusCode > 299 { - return nil, responseError(res) - } var v struct { Contact []string @@ -649,59 +692,6 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun }, nil } -// retryPostJWS will retry calls to postJWS if there is a badNonce error, -// clearing the stored nonces after each error. -// If the response was 4XX-5XX, then responseError is called on the body, -// the body is closed, and the error returned. -func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { - sleep := sleeper(ctx) - for { - res, err := c.postJWS(ctx, key, url, body) - if err != nil { - return nil, err - } - // handle errors 4XX-5XX with responseError - if res.StatusCode >= 400 && res.StatusCode <= 599 { - err := responseError(res) - res.Body.Close() - // according to spec badNonce is urn:ietf:params:acme:error:badNonce - // however, acme servers in the wild return their version of the error - // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 - if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") { - // clear any nonces that we might've stored that might now be - // considered bad - c.clearNonces() - retry := res.Header.Get("Retry-After") - if err := sleep(retry, 1); err != nil { - return nil, err - } - continue - } - return nil, err - } - return res, nil - } -} - -// postJWS signs the body with the given key and POSTs it to the provided url. -// The body argument must be JSON-serializable. -func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { - nonce, err := c.popNonce(ctx, url) - if err != nil { - return nil, err - } - b, err := jwsEncodeJSON(body, key, nonce) - if err != nil { - return nil, err - } - res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b)) - if err != nil { - return nil, err - } - c.addNonce(res.Header) - return res, nil -} - // popNonce returns a nonce value previously stored with c.addNonce // or fetches a fresh one from the given URL. func (c *Client) popNonce(ctx context.Context, url string) (string, error) { @@ -742,58 +732,12 @@ func (c *Client) addNonce(h http.Header) { c.nonces[v] = struct{}{} } -func (c *Client) httpClient() *http.Client { - if c.HTTPClient != nil { - return c.HTTPClient - } - return http.DefaultClient -} - -func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) { - req, err := http.NewRequest("GET", urlStr, nil) - if err != nil { - return nil, err - } - return c.do(ctx, req) -} - -func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", urlStr, nil) - if err != nil { - return nil, err - } - return c.do(ctx, req) -} - -func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", urlStr, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", contentType) - return c.do(ctx, req) -} - -func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) { - res, err := c.httpClient().Do(req.WithContext(ctx)) - if err != nil { - select { - case <-ctx.Done(): - // Prefer the unadorned context error. - // (The acme package had tests assuming this, previously from ctxhttp's - // behavior, predating net/http supporting contexts natively) - // TODO(bradfitz): reconsider this in the future. But for now this - // requires no test updates. - return nil, ctx.Err() - default: - return nil, err - } - } - return res, nil -} - func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { - resp, err := c.head(ctx, url) + r, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return "", err + } + resp, err := c.doNoRetry(ctx, r) if err != nil { return "", err } @@ -845,24 +789,6 @@ func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bo return cert, nil } -// responseError creates an error of Error type from resp. -func responseError(resp *http.Response) error { - // don't care if ReadAll returns an error: - // json.Unmarshal will fail in that case anyway - b, _ := ioutil.ReadAll(resp.Body) - e := &wireError{Status: resp.StatusCode} - if err := json.Unmarshal(b, e); err != nil { - // this is not a regular error response: - // populate detail with anything we received, - // e.Status will already contain HTTP response code value - e.Detail = string(b) - if e.Detail == "" { - e.Detail = resp.Status - } - } - return e.error(resp.Header) -} - // chainCert fetches CA certificate chain recursively by following "up" links. // Each recursive call increments the depth by 1, resulting in an error // if the recursion level reaches maxChainLen. @@ -873,14 +799,11 @@ func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte return nil, errors.New("acme: certificate chain is too deep") } - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, responseError(res) - } b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) if err != nil { return nil, err @@ -925,65 +848,6 @@ func linkHeader(h http.Header, rel string) []string { return links } -// sleeper returns a function that accepts the Retry-After HTTP header value -// and an increment that's used with backoff to increasingly sleep on -// consecutive calls until the context is done. If the Retry-After header -// cannot be parsed, then backoff is used with a maximum sleep time of 10 -// seconds. -func sleeper(ctx context.Context) func(ra string, inc int) error { - var count int - return func(ra string, inc int) error { - count += inc - d := backoff(count, 10*time.Second) - d = retryAfter(ra, d) - wakeup := time.NewTimer(d) - defer wakeup.Stop() - select { - case <-ctx.Done(): - return ctx.Err() - case <-wakeup.C: - return nil - } - } -} - -// retryAfter parses a Retry-After HTTP header value, -// trying to convert v into an int (seconds) or use http.ParseTime otherwise. -// It returns d if v cannot be parsed. -func retryAfter(v string, d time.Duration) time.Duration { - if i, err := strconv.Atoi(v); err == nil { - return time.Duration(i) * time.Second - } - t, err := http.ParseTime(v) - if err != nil { - return d - } - return t.Sub(timeNow()) -} - -// backoff computes a duration after which an n+1 retry iteration should occur -// using truncated exponential backoff algorithm. -// -// The n argument is always bounded between 0 and 30. -// The max argument defines upper bound for the returned value. -func backoff(n int, max time.Duration) time.Duration { - if n < 0 { - n = 0 - } - if n > 30 { - n = 30 - } - var d time.Duration - if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { - d = time.Duration(x.Int64()) * time.Millisecond - } - d += time.Duration(1< max { - return max - } - return d -} - // keyAuth generates a key authorization string for a given token. func keyAuth(pub crypto.PublicKey, token string) (string, error) { th, err := JWKThumbprint(pub) @@ -993,15 +857,25 @@ func keyAuth(pub crypto.PublicKey, token string) (string, error) { return fmt.Sprintf("%s.%s", token, th), nil } +// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges. +func defaultTLSChallengeCertTemplate() *x509.Certificate { + return &x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + } +} + // tlsChallengeCert creates a temporary certificate for TLS-SNI challenges // with the given SANs and auto-generated public/private key pair. // The Subject Common Name is set to the first SAN to aid debugging. // To create a cert with a custom key pair, specify WithKey option. func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { - var ( - key crypto.Signer - tmpl *x509.Certificate - ) + var key crypto.Signer + tmpl := defaultTLSChallengeCertTemplate() for _, o := range opt { switch o := o.(type) { case *certOptKey: @@ -1010,7 +884,7 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { } key = o.key case *certOptTemplate: - var t = *(*x509.Certificate)(o) // shallow copy is ok + t := *(*x509.Certificate)(o) // shallow copy is ok tmpl = &t default: // package's fault, if we let this happen: @@ -1023,16 +897,6 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { return tls.Certificate{}, err } } - if tmpl == nil { - tmpl = &x509.Certificate{ - SerialNumber: big.NewInt(1), - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - BasicConstraintsValid: true, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - } - } tmpl.DNSNames = san if len(san) > 0 { tmpl.Subject.CommonName = san[0] diff --git a/vendor/golang.org/x/crypto/acme/acme_test.go b/vendor/golang.org/x/crypto/acme/acme_test.go index 89f2efa..ef1fe47 100644 --- a/vendor/golang.org/x/crypto/acme/acme_test.go +++ b/vendor/golang.org/x/crypto/acme/acme_test.go @@ -13,9 +13,9 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" - "io/ioutil" "math/big" "net/http" "net/http/httptest" @@ -485,95 +485,98 @@ func TestGetAuthorization(t *testing.T) { } func TestWaitAuthorization(t *testing.T) { - var count int - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - count++ - w.Header().Set("Retry-After", "0") - if count > 1 { - fmt.Fprintf(w, `{"status":"valid"}`) - return + t.Run("wait loop", func(t *testing.T) { + var count int + authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Retry-After", "0") + if count > 1 { + fmt.Fprintf(w, `{"status":"valid"}`) + return + } + fmt.Fprintf(w, `{"status":"pending"}`) + }) + if err != nil { + t.Fatalf("non-nil error: %v", err) } - fmt.Fprintf(w, `{"status":"pending"}`) - })) + if authz == nil { + t.Fatal("authz is nil") + } + }) + t.Run("invalid status", func(t *testing.T) { + _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, `{"status":"invalid"}`) + }) + if _, ok := err.(*AuthorizationError); !ok { + t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err) + } + }) + t.Run("non-retriable error", func(t *testing.T) { + const code = http.StatusBadRequest + _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(code) + }) + res, ok := err.(*Error) + if !ok { + t.Fatalf("err is %v (%T); want a non-nil *Error", err, err) + } + if res.StatusCode != code { + t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code) + } + }) + for _, code := range []int{http.StatusTooManyRequests, http.StatusInternalServerError} { + t.Run(fmt.Sprintf("retriable %d error", code), func(t *testing.T) { + var count int + authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Retry-After", "0") + if count > 1 { + fmt.Fprintf(w, `{"status":"valid"}`) + return + } + w.WriteHeader(code) + }) + if err != nil { + t.Fatalf("non-nil error: %v", err) + } + if authz == nil { + t.Fatal("authz is nil") + } + }) + } + t.Run("context cancel", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) + defer cancel() + _, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Retry-After", "60") + fmt.Fprintf(w, `{"status":"pending"}`) + }) + if err == nil { + t.Error("err is nil") + } + }) +} +func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc) (*Authorization, error) { + t.Helper() + ts := httptest.NewServer(h) defer ts.Close() - type res struct { authz *Authorization err error } - done := make(chan res) - defer close(done) + ch := make(chan res, 1) go func() { var client Client - a, err := client.WaitAuthorization(context.Background(), ts.URL) - done <- res{a, err} + a, err := client.WaitAuthorization(ctx, ts.URL) + ch <- res{a, err} }() - - select { - case <-time.After(5 * time.Second): - t.Fatal("WaitAuthz took too long to return") - case res := <-done: - if res.err != nil { - t.Fatalf("res.err = %v", res.err) - } - if res.authz == nil { - t.Fatal("res.authz is nil") - } - } -} - -func TestWaitAuthorizationInvalid(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, `{"status":"invalid"}`) - })) - defer ts.Close() - - res := make(chan error) - defer close(res) - go func() { - var client Client - _, err := client.WaitAuthorization(context.Background(), ts.URL) - res <- err - }() - select { case <-time.After(3 * time.Second): - t.Fatal("WaitAuthz took too long to return") - case err := <-res: - if err == nil { - t.Error("err is nil") - } - if _, ok := err.(*AuthorizationError); !ok { - t.Errorf("err is %T; want *AuthorizationError", err) - } - } -} - -func TestWaitAuthorizationCancel(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Retry-After", "60") - fmt.Fprintf(w, `{"status":"pending"}`) - })) - defer ts.Close() - - res := make(chan error) - defer close(res) - go func() { - var client Client - ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) - defer cancel() - _, err := client.WaitAuthorization(ctx, ts.URL) - res <- err - }() - - select { - case <-time.After(time.Second): - t.Fatal("WaitAuthz took too long to return") - case err := <-res: - if err == nil { - t.Error("err is nil") - } + t.Fatal("WaitAuthorization took too long to return") + case v := <-ch: + return v.authz, v.err } + panic("runWaitAuthorization: out of select") } func TestRevokeAuthorization(t *testing.T) { @@ -600,7 +603,7 @@ func TestRevokeAuthorization(t *testing.T) { t.Errorf("req.Delete is false") } case "/2": - w.WriteHeader(http.StatusInternalServerError) + w.WriteHeader(http.StatusBadRequest) } })) defer ts.Close() @@ -821,7 +824,7 @@ func TestFetchCertRetry(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if count < 1 { w.Header().Set("Retry-After", "0") - w.WriteHeader(http.StatusAccepted) + w.WriteHeader(http.StatusTooManyRequests) count++ return } @@ -1068,44 +1071,6 @@ func TestNonce_postJWS(t *testing.T) { } } -func TestRetryPostJWS(t *testing.T) { - var count int - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - count++ - w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) - if r.Method == "HEAD" { - // We expect the client to do 2 head requests to fetch - // nonces, one to start and another after getting badNonce - return - } - - head, err := decodeJWSHead(r) - if err != nil { - t.Errorf("decodeJWSHead: %v", err) - } else if head.Nonce == "" { - t.Error("head.Nonce is empty") - } else if head.Nonce == "nonce1" { - // return a badNonce error to force the call to retry - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`)) - return - } - // Make client.Authorize happy; we're not testing its result. - w.WriteHeader(http.StatusCreated) - w.Write([]byte(`{"status":"valid"}`)) - })) - defer ts.Close() - - client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}} - // This call will fail with badNonce, causing a retry - if _, err := client.Authorize(context.Background(), "example.com"); err != nil { - t.Errorf("client.Authorize 1: %v", err) - } - if count != 4 { - t.Errorf("total requests count: %d; want 4", count) - } -} - func TestLinkHeader(t *testing.T) { h := http.Header{"Link": { `;rel="next"`, @@ -1129,37 +1094,6 @@ func TestLinkHeader(t *testing.T) { } } -func TestErrorResponse(t *testing.T) { - s := `{ - "status": 400, - "type": "urn:acme:error:xxx", - "detail": "text" - }` - res := &http.Response{ - StatusCode: 400, - Status: "400 Bad Request", - Body: ioutil.NopCloser(strings.NewReader(s)), - Header: http.Header{"X-Foo": {"bar"}}, - } - err := responseError(res) - v, ok := err.(*Error) - if !ok { - t.Fatalf("err = %+v (%T); want *Error type", err, err) - } - if v.StatusCode != 400 { - t.Errorf("v.StatusCode = %v; want 400", v.StatusCode) - } - if v.ProblemType != "urn:acme:error:xxx" { - t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType) - } - if v.Detail != "text" { - t.Errorf("v.Detail = %q; want text", v.Detail) - } - if !reflect.DeepEqual(v.Header, res.Header) { - t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header) - } -} - func TestTLSSNI01ChallengeCert(t *testing.T) { const ( token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" @@ -1227,6 +1161,58 @@ func TestTLSSNI02ChallengeCert(t *testing.T) { } } +func TestTLSALPN01ChallengeCert(t *testing.T) { + const ( + token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" + keyAuth = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA." + testKeyECThumbprint + // echo -n | shasum -a 256 + h = "0420dbbd5eefe7b4d06eb9d1d9f5acb4c7cda27d320e4b30332f0b6cb441734ad7b0" + domain = "example.com" + ) + + extValue, err := hex.DecodeString(h) + if err != nil { + t.Fatal(err) + } + + client := &Client{Key: testKeyEC} + tlscert, err := client.TLSALPN01ChallengeCert(token, domain) + if err != nil { + t.Fatal(err) + } + + if n := len(tlscert.Certificate); n != 1 { + t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) + } + cert, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Fatal(err) + } + names := []string{domain} + if !reflect.DeepEqual(cert.DNSNames, names) { + t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) + } + if cn := cert.Subject.CommonName; cn != domain { + t.Errorf("CommonName = %q; want %q", cn, domain) + } + acmeExts := []pkix.Extension{} + for _, ext := range cert.Extensions { + if idPeACMEIdentifierV1.Equal(ext.Id) { + acmeExts = append(acmeExts, ext) + } + } + if len(acmeExts) != 1 { + t.Errorf("acmeExts = %v; want exactly one", acmeExts) + } + if !acmeExts[0].Critical { + t.Errorf("acmeExt.Critical = %v; want true", acmeExts[0].Critical) + } + if bytes.Compare(acmeExts[0].Value, extValue) != 0 { + t.Errorf("acmeExt.Value = %v; want %v", acmeExts[0].Value, extValue) + } + +} + func TestTLSChallengeCertOpt(t *testing.T) { key, err := rsa.GenerateKey(rand.Reader, 512) if err != nil { @@ -1325,28 +1311,3 @@ func TestDNS01ChallengeRecord(t *testing.T) { t.Errorf("val = %q; want %q", val, value) } } - -func TestBackoff(t *testing.T) { - tt := []struct{ min, max time.Duration }{ - {time.Second, 2 * time.Second}, - {2 * time.Second, 3 * time.Second}, - {4 * time.Second, 5 * time.Second}, - {8 * time.Second, 9 * time.Second}, - } - for i, test := range tt { - d := backoff(i, time.Minute) - if d < test.min || test.max < d { - t.Errorf("%d: d = %v; want between %v and %v", i, d, test.min, test.max) - } - } - - min, max := time.Second, 2*time.Second - if d := backoff(-1, time.Minute); d < min || max < d { - t.Errorf("d = %v; want between %v and %v", d, min, max) - } - - bound := 10 * time.Second - if d := backoff(100, bound); d != bound { - t.Errorf("d = %v; want %v", d, bound) - } -} diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go index 453e722..4c2fc07 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/autocert.go +++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go @@ -27,7 +27,6 @@ import ( "net" "net/http" "path" - "strconv" "strings" "sync" "time" @@ -45,7 +44,7 @@ var createCertRetryAfter = time.Minute var pseudoRand *lockedMathRand func init() { - src := mathrand.NewSource(timeNow().UnixNano()) + src := mathrand.NewSource(time.Now().UnixNano()) pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} } @@ -82,9 +81,9 @@ func defaultHostPolicy(context.Context, string) error { } // Manager is a stateful certificate manager built on top of acme.Client. -// It obtains and refreshes certificates automatically using "tls-sni-01", -// "tls-sni-02" and "http-01" challenge types, as well as providing them -// to a TLS server via tls.Config. +// It obtains and refreshes certificates automatically using "tls-alpn-01", +// "tls-sni-01", "tls-sni-02" and "http-01" challenge types, +// as well as providing them to a TLS server via tls.Config. // // You must specify a cache implementation, such as DirCache, // to reuse obtained certificates across program restarts. @@ -99,11 +98,11 @@ type Manager struct { // To always accept the terms, the callers can use AcceptTOS. Prompt func(tosURL string) bool - // Cache optionally stores and retrieves previously-obtained certificates. - // If nil, certs will only be cached for the lifetime of the Manager. + // Cache optionally stores and retrieves previously-obtained certificates + // and other state. If nil, certs will only be cached for the lifetime of + // the Manager. Multiple Managers can share the same Cache. // - // Manager passes the Cache certificates data encoded in PEM, with private/public - // parts combined in a single Cache.Put call, private key first. + // Using a persistent Cache, such as DirCache, is strongly recommended. Cache Cache // HostPolicy controls which domains the Manager will attempt @@ -128,8 +127,10 @@ type Manager struct { // Client is used to perform low-level operations, such as account registration // and requesting new certificates. + // // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL - // directory endpoint and a newly-generated ECDSA P-256 key. + // as directory endpoint. If the Client.Key is nil, a new ECDSA P-256 key is + // generated and, if Cache is not nil, stored in cache. // // Mutating the field after the first call of GetCertificate method will have no effect. Client *acme.Client @@ -141,22 +142,30 @@ type Manager struct { // If the Client's account key is already registered, Email is not used. Email string - // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys. + // ForceRSA used to make the Manager generate RSA certificates. It is now ignored. // - // If false, a default is used. Currently the default - // is EC-based keys using the P-256 curve. + // Deprecated: the Manager will request the correct type of certificate based + // on what each client supports. ForceRSA bool + // ExtraExtensions are used when generating a new CSR (Certificate Request), + // thus allowing customization of the resulting certificate. + // For instance, TLS Feature Extension (RFC 7633) can be used + // to prevent an OCSP downgrade attack. + // + // The field value is passed to crypto/x509.CreateCertificateRequest + // in the template's ExtraExtensions field as is. + ExtraExtensions []pkix.Extension + clientMu sync.Mutex client *acme.Client // initialized by acmeClient method stateMu sync.Mutex - state map[string]*certState // keyed by domain name + state map[certKey]*certState // renewal tracks the set of domains currently running renewal timers. - // It is keyed by domain name. renewalMu sync.Mutex - renewal map[string]*domainRenewal + renewal map[certKey]*domainRenewal // tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens. tokensMu sync.RWMutex @@ -168,21 +177,60 @@ type Manager struct { // to be provisioned. // The entries are stored for the duration of the authorization flow. httpTokens map[string][]byte - // certTokens contains temporary certificates for tls-sni challenges + // certTokens contains temporary certificates for tls-sni and tls-alpn challenges // and is keyed by token domain name, which matches server name of ClientHello. - // Keys always have ".acme.invalid" suffix. + // Keys always have ".acme.invalid" suffix for tls-sni. Otherwise, they are domain names + // for tls-alpn. // The entries are stored for the duration of the authorization flow. certTokens map[string]*tls.Certificate + // nowFunc, if not nil, returns the current time. This may be set for + // testing purposes. + nowFunc func() time.Time +} + +// certKey is the key by which certificates are tracked in state, renewal and cache. +type certKey struct { + domain string // without trailing dot + isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA) + isToken bool // tls-based challenge token cert; key type is undefined regardless of isRSA +} + +func (c certKey) String() string { + if c.isToken { + return c.domain + "+token" + } + if c.isRSA { + return c.domain + "+rsa" + } + return c.domain +} + +// TLSConfig creates a new TLS config suitable for net/http.Server servers, +// supporting HTTP/2 and the tls-alpn-01 ACME challenge type. +func (m *Manager) TLSConfig() *tls.Config { + return &tls.Config{ + GetCertificate: m.GetCertificate, + NextProtos: []string{ + "h2", "http/1.1", // enable HTTP/2 + acme.ALPNProto, // enable tls-alpn ACME challenges + }, + } } // GetCertificate implements the tls.Config.GetCertificate hook. // It provides a TLS certificate for hello.ServerName host, including answering -// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored. +// tls-alpn-01 and *.acme.invalid (tls-sni-01 and tls-sni-02) challenges. +// All other fields of hello are ignored. // // If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting // a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. // The error is propagated back to the caller of GetCertificate and is user-visible. // This does not affect cached certs. See HostPolicy field description for more details. +// +// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will +// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler +// for http-01. (The tls-sni-* challenges have been deprecated by popular ACME providers +// due to security issues in the ecosystem.) func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { if m.Prompt == nil { return nil, errors.New("acme/autocert: Manager.Prompt not set") @@ -195,7 +243,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, if !strings.Contains(strings.Trim(name, "."), ".") { return nil, errors.New("acme/autocert: server name component count invalid") } - if strings.ContainsAny(name, `/\`) { + if strings.ContainsAny(name, `+/\`) { return nil, errors.New("acme/autocert: server name contains invalid character") } @@ -204,14 +252,17 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() - // check whether this is a token cert requested for TLS-SNI challenge - if strings.HasSuffix(name, ".acme.invalid") { + // Check whether this is a token cert requested for TLS-SNI or TLS-ALPN challenge. + if wantsTokenCert(hello) { m.tokensMu.RLock() defer m.tokensMu.RUnlock() + // It's ok to use the same token cert key for both tls-sni and tls-alpn + // because there's always at most 1 token cert per on-going domain authorization. + // See m.verify for details. if cert := m.certTokens[name]; cert != nil { return cert, nil } - if cert, err := m.cacheGet(ctx, name); err == nil { + if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil { return cert, nil } // TODO: cache error results? @@ -219,8 +270,11 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } // regular domain - name = strings.TrimSuffix(name, ".") // golang.org/issue/18114 - cert, err := m.cert(ctx, name) + ck := certKey{ + domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 + isRSA: !supportsECDSA(hello), + } + cert, err := m.cert(ctx, ck) if err == nil { return cert, nil } @@ -232,14 +286,71 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, if err := m.hostPolicy()(ctx, name); err != nil { return nil, err } - cert, err = m.createCert(ctx, name) + cert, err = m.createCert(ctx, ck) if err != nil { return nil, err } - m.cachePut(ctx, name, cert) + m.cachePut(ctx, ck, cert) return cert, nil } +// wantsTokenCert reports whether a TLS request with SNI is made by a CA server +// for a challenge verification. +func wantsTokenCert(hello *tls.ClientHelloInfo) bool { + // tls-alpn-01 + if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto { + return true + } + // tls-sni-xx + return strings.HasSuffix(hello.ServerName, ".acme.invalid") +} + +func supportsECDSA(hello *tls.ClientHelloInfo) bool { + // The "signature_algorithms" extension, if present, limits the key exchange + // algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1. + if hello.SignatureSchemes != nil { + ecdsaOK := false + schemeLoop: + for _, scheme := range hello.SignatureSchemes { + const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10 + switch scheme { + case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, + tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512: + ecdsaOK = true + break schemeLoop + } + } + if !ecdsaOK { + return false + } + } + if hello.SupportedCurves != nil { + ecdsaOK := false + for _, curve := range hello.SupportedCurves { + if curve == tls.CurveP256 { + ecdsaOK = true + break + } + } + if !ecdsaOK { + return false + } + } + for _, suite := range hello.CipherSuites { + switch suite { + case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: + return true + } + } + return false +} + // HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. // It returns an http.Handler that responds to the challenges and must be // running on port 80. If it receives a request that is not an ACME challenge, @@ -253,8 +364,8 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, // Because the fallback handler is run with unencrypted port 80 requests, // the fallback should not serve TLS-only requests. // -// If HTTPHandler is never called, the Manager will only use TLS SNI -// challenges for domain verification. +// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" +// challenge for domain verification. func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { m.tokensMu.Lock() defer m.tokensMu.Unlock() @@ -305,16 +416,16 @@ func stripPort(hostport string) string { // cert returns an existing certificate either from m.state or cache. // If a certificate is found in cache but not in m.state, the latter will be filled // with the cached value. -func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) { +func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) { m.stateMu.Lock() - if s, ok := m.state[name]; ok { + if s, ok := m.state[ck]; ok { m.stateMu.Unlock() s.RLock() defer s.RUnlock() return s.tlscert() } defer m.stateMu.Unlock() - cert, err := m.cacheGet(ctx, name) + cert, err := m.cacheGet(ctx, ck) if err != nil { return nil, err } @@ -323,25 +434,25 @@ func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, erro return nil, errors.New("acme/autocert: private key cannot sign") } if m.state == nil { - m.state = make(map[string]*certState) + m.state = make(map[certKey]*certState) } s := &certState{ key: signer, cert: cert.Certificate, leaf: cert.Leaf, } - m.state[name] = s - go m.renew(name, s.key, s.leaf.NotAfter) + m.state[ck] = s + go m.renew(ck, s.key, s.leaf.NotAfter) return cert, nil } // cacheGet always returns a valid certificate, or an error otherwise. -// If a cached certficate exists but is not valid, ErrCacheMiss is returned. -func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) { +// If a cached certificate exists but is not valid, ErrCacheMiss is returned. +func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) { if m.Cache == nil { return nil, ErrCacheMiss } - data, err := m.Cache.Get(ctx, domain) + data, err := m.Cache.Get(ctx, ck.String()) if err != nil { return nil, err } @@ -372,7 +483,7 @@ func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate } // verify and create TLS cert - leaf, err := validCert(domain, pubDER, privKey) + leaf, err := validCert(ck, pubDER, privKey, m.now()) if err != nil { return nil, ErrCacheMiss } @@ -384,7 +495,7 @@ func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate return tlscert, nil } -func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error { +func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error { if m.Cache == nil { return nil } @@ -416,7 +527,7 @@ func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Cert } } - return m.Cache.Put(ctx, domain, buf.Bytes()) + return m.Cache.Put(ctx, ck.String(), buf.Bytes()) } func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { @@ -433,9 +544,9 @@ func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { // // If the domain is already being verified, it waits for the existing verification to complete. // Either way, createCert blocks for the duration of the whole process. -func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) { +func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) { // TODO: maybe rewrite this whole piece using sync.Once - state, err := m.certState(domain) + state, err := m.certState(ck) if err != nil { return nil, err } @@ -453,44 +564,44 @@ func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certifica defer state.Unlock() state.locked = false - der, leaf, err := m.authorizedCert(ctx, state.key, domain) + der, leaf, err := m.authorizedCert(ctx, state.key, ck) if err != nil { // Remove the failed state after some time, // making the manager call createCert again on the following TLS hello. time.AfterFunc(createCertRetryAfter, func() { - defer testDidRemoveState(domain) + defer testDidRemoveState(ck) m.stateMu.Lock() defer m.stateMu.Unlock() // Verify the state hasn't changed and it's still invalid // before deleting. - s, ok := m.state[domain] + s, ok := m.state[ck] if !ok { return } - if _, err := validCert(domain, s.cert, s.key); err == nil { + if _, err := validCert(ck, s.cert, s.key, m.now()); err == nil { return } - delete(m.state, domain) + delete(m.state, ck) }) return nil, err } state.cert = der state.leaf = leaf - go m.renew(domain, state.key, state.leaf.NotAfter) + go m.renew(ck, state.key, state.leaf.NotAfter) return state.tlscert() } // certState returns a new or existing certState. // If a new certState is returned, state.exist is false and the state is locked. // The returned error is non-nil only in the case where a new state could not be created. -func (m *Manager) certState(domain string) (*certState, error) { +func (m *Manager) certState(ck certKey) (*certState, error) { m.stateMu.Lock() defer m.stateMu.Unlock() if m.state == nil { - m.state = make(map[string]*certState) + m.state = make(map[certKey]*certState) } // existing state - if state, ok := m.state[domain]; ok { + if state, ok := m.state[ck]; ok { return state, nil } @@ -499,7 +610,7 @@ func (m *Manager) certState(domain string) (*certState, error) { err error key crypto.Signer ) - if m.ForceRSA { + if ck.isRSA { key, err = rsa.GenerateKey(rand.Reader, 2048) } else { key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -513,22 +624,22 @@ func (m *Manager) certState(domain string) (*certState, error) { locked: true, } state.Lock() // will be unlocked by m.certState caller - m.state[domain] = state + m.state[ck] = state return state, nil } // authorizedCert starts the domain ownership verification process and requests a new cert upon success. // The key argument is the certificate private key. -func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) { +func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { client, err := m.acmeClient(ctx) if err != nil { return nil, nil, err } - if err := m.verify(ctx, client, domain); err != nil { + if err := m.verify(ctx, client, ck.domain); err != nil { return nil, nil, err } - csr, err := certRequest(key, domain) + csr, err := certRequest(key, ck.domain, m.ExtraExtensions) if err != nil { return nil, nil, err } @@ -536,25 +647,55 @@ func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain if err != nil { return nil, nil, err } - leaf, err = validCert(domain, der, key) + leaf, err = validCert(ck, der, key, m.now()) if err != nil { return nil, nil, err } return der, leaf, nil } +// revokePendingAuthz revokes all authorizations idenfied by the elements of uri slice. +// It ignores revocation errors. +func (m *Manager) revokePendingAuthz(ctx context.Context, uri []string) { + client, err := m.acmeClient(ctx) + if err != nil { + return + } + for _, u := range uri { + client.RevokeAuthorization(ctx, u) + } +} + // verify runs the identifier (domain) authorization flow // using each applicable ACME challenge type. func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error { // The list of challenge types we'll try to fulfill // in this specific order. - challengeTypes := []string{"tls-sni-02", "tls-sni-01"} + challengeTypes := []string{"tls-alpn-01", "tls-sni-02", "tls-sni-01"} m.tokensMu.RLock() if m.tryHTTP01 { challengeTypes = append(challengeTypes, "http-01") } m.tokensMu.RUnlock() + // Keep track of pending authzs and revoke the ones that did not validate. + pendingAuthzs := make(map[string]bool) + defer func() { + var uri []string + for k, pending := range pendingAuthzs { + if pending { + uri = append(uri, k) + } + } + if len(uri) > 0 { + // Use "detached" background context. + // The revocations need not happen in the current verification flow. + go m.revokePendingAuthz(context.Background(), uri) + } + }() + + // errs accumulates challenge failure errors, printed if all fail + errs := make(map[*acme.Challenge]error) var nextTyp int // challengeType index of the next challenge type to try for { // Start domain authorization and get the challenge. @@ -571,6 +712,8 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI) } + pendingAuthzs[authz.URI] = true + // Pick the next preferred challenge. var chal *acme.Challenge for chal == nil && nextTyp < len(challengeTypes) { @@ -578,28 +721,44 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string nextTyp++ } if chal == nil { - return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes) + errorMsg := fmt.Sprintf("acme/autocert: unable to authorize %q", domain) + for chal, err := range errs { + errorMsg += fmt.Sprintf("; challenge %q failed with error: %v", chal.Type, err) + } + return errors.New(errorMsg) } - cleanup, err := m.fulfill(ctx, client, chal) + cleanup, err := m.fulfill(ctx, client, chal, domain) if err != nil { + errs[chal] = err continue } defer cleanup() if _, err := client.Accept(ctx, chal); err != nil { + errs[chal] = err continue } // A challenge is fulfilled and accepted: wait for the CA to validate. - if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil { - return nil + if _, err := client.WaitAuthorization(ctx, authz.URI); err != nil { + errs[chal] = err + continue } + delete(pendingAuthzs, authz.URI) + return nil } } // fulfill provisions a response to the challenge chal. // The cleanup is non-nil only if provisioning succeeded. -func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) { +func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) { switch chal.Type { + case "tls-alpn-01": + cert, err := client.TLSALPN01ChallengeCert(chal.Token, domain) + if err != nil { + return nil, err + } + m.putCertToken(ctx, domain, &cert) + return func() { go m.deleteCertToken(domain) }, nil case "tls-sni-01": cert, name, err := client.TLSSNI01ChallengeCert(chal.Token) if err != nil { @@ -635,8 +794,8 @@ func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { return nil } -// putCertToken stores the cert under the named key in both m.certTokens map -// and m.Cache. +// putCertToken stores the token certificate with the specified name +// in both m.certTokens map and m.Cache. func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { m.tokensMu.Lock() defer m.tokensMu.Unlock() @@ -644,17 +803,18 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi m.certTokens = make(map[string]*tls.Certificate) } m.certTokens[name] = cert - m.cachePut(ctx, name, cert) + m.cachePut(ctx, certKey{domain: name, isToken: true}, cert) } -// deleteCertToken removes the token certificate for the specified domain name +// deleteCertToken removes the token certificate with the specified name // from both m.certTokens map and m.Cache. func (m *Manager) deleteCertToken(name string) { m.tokensMu.Lock() defer m.tokensMu.Unlock() delete(m.certTokens, name) if m.Cache != nil { - m.Cache.Delete(context.Background(), name) + ck := certKey{domain: name, isToken: true} + m.Cache.Delete(context.Background(), ck.String()) } } @@ -705,7 +865,7 @@ func (m *Manager) deleteHTTPToken(tokenPath string) { // httpTokenCacheKey returns a key at which an http-01 token value may be stored // in the Manager's optional Cache. func httpTokenCacheKey(tokenPath string) string { - return "http-01-" + path.Base(tokenPath) + return path.Base(tokenPath) + "+http-01" } // renew starts a cert renewal timer loop, one per domain. @@ -716,18 +876,18 @@ func httpTokenCacheKey(tokenPath string) string { // // The key argument is a certificate private key. // The exp argument is the cert expiration time (NotAfter). -func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) { +func (m *Manager) renew(ck certKey, key crypto.Signer, exp time.Time) { m.renewalMu.Lock() defer m.renewalMu.Unlock() - if m.renewal[domain] != nil { + if m.renewal[ck] != nil { // another goroutine is already on it return } if m.renewal == nil { - m.renewal = make(map[string]*domainRenewal) + m.renewal = make(map[certKey]*domainRenewal) } - dr := &domainRenewal{m: m, domain: domain, key: key} - m.renewal[domain] = dr + dr := &domainRenewal{m: m, ck: ck, key: key} + m.renewal[ck] = dr dr.start(exp) } @@ -743,7 +903,10 @@ func (m *Manager) stopRenew() { } func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { - const keyName = "acme_account.key" + const keyName = "acme_account+key" + + // Previous versions of autocert stored the value under a different key. + const legacyKeyName = "acme_account.key" genKey := func() (*ecdsa.PrivateKey, error) { return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -754,6 +917,9 @@ func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { } data, err := m.Cache.Get(ctx, keyName) + if err == ErrCacheMiss { + data, err = m.Cache.Get(ctx, legacyKeyName) + } if err == ErrCacheMiss { key, err := genKey() if err != nil { @@ -825,6 +991,13 @@ func (m *Manager) renewBefore() time.Duration { return 720 * time.Hour // 30 days } +func (m *Manager) now() time.Time { + if m.nowFunc != nil { + return m.nowFunc() + } + return time.Now() +} + // certState is ready when its mutex is unlocked for reading. type certState struct { sync.RWMutex @@ -850,12 +1023,12 @@ func (s *certState) tlscert() (*tls.Certificate, error) { }, nil } -// certRequest creates a certificate request for the given common name cn -// and optional SANs. -func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) { +// certRequest generates a CSR for the given common name cn and optional SANs. +func certRequest(key crypto.Signer, cn string, ext []pkix.Extension, san ...string) ([]byte, error) { req := &x509.CertificateRequest{ - Subject: pkix.Name{CommonName: cn}, - DNSNames: san, + Subject: pkix.Name{CommonName: cn}, + DNSNames: san, + ExtraExtensions: ext, } return x509.CreateCertificateRequest(rand.Reader, req, key) } @@ -886,12 +1059,12 @@ func parsePrivateKey(der []byte) (crypto.Signer, error) { return nil, errors.New("acme/autocert: failed to parse private key") } -// validCert parses a cert chain provided as der argument and verifies the leaf, der[0], -// corresponds to the private key, as well as the domain match and expiration dates. -// It doesn't do any revocation checking. +// validCert parses a cert chain provided as der argument and verifies the leaf and der[0] +// correspond to the private key, the domain and key type match, and expiration dates +// are valid. It doesn't do any revocation checking. // // The returned value is the verified leaf cert. -func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) { +func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf *x509.Certificate, err error) { // parse public part(s) var n int for _, b := range der { @@ -903,22 +1076,21 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi n += copy(pub[n:], b) } x509Cert, err := x509.ParseCertificates(pub) - if len(x509Cert) == 0 { + if err != nil || len(x509Cert) == 0 { return nil, errors.New("acme/autocert: no public key found") } // verify the leaf is not expired and matches the domain name leaf = x509Cert[0] - now := timeNow() if now.Before(leaf.NotBefore) { return nil, errors.New("acme/autocert: certificate is not valid yet") } if now.After(leaf.NotAfter) { return nil, errors.New("acme/autocert: expired certificate") } - if err := leaf.VerifyHostname(domain); err != nil { + if err := leaf.VerifyHostname(ck.domain); err != nil { return nil, err } - // ensure the leaf corresponds to the private key + // ensure the leaf corresponds to the private key and matches the certKey type switch pub := leaf.PublicKey.(type) { case *rsa.PublicKey: prv, ok := key.(*rsa.PrivateKey) @@ -928,6 +1100,9 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi if pub.N.Cmp(prv.N) != 0 { return nil, errors.New("acme/autocert: private key does not match public key") } + if !ck.isRSA && !ck.isToken { + return nil, errors.New("acme/autocert: key type does not match expected value") + } case *ecdsa.PublicKey: prv, ok := key.(*ecdsa.PrivateKey) if !ok { @@ -936,22 +1111,15 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { return nil, errors.New("acme/autocert: private key does not match public key") } + if ck.isRSA && !ck.isToken { + return nil, errors.New("acme/autocert: key type does not match expected value") + } default: return nil, errors.New("acme/autocert: unknown public key algorithm") } return leaf, nil } -func retryAfter(v string) time.Duration { - if i, err := strconv.Atoi(v); err == nil { - return time.Duration(i) * time.Second - } - if t, err := http.ParseTime(v); err == nil { - return t.Sub(timeNow()) - } - return time.Second -} - type lockedMathRand struct { sync.Mutex rnd *mathrand.Rand @@ -966,8 +1134,6 @@ func (r *lockedMathRand) int63n(max int64) int64 { // For easier testing. var ( - timeNow = time.Now - // Called when a state is removed. - testDidRemoveState = func(domain string) {} + testDidRemoveState = func(certKey) {} ) diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go index 2da1912..95e12e1 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go +++ b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go @@ -5,6 +5,7 @@ package autocert import ( + "bytes" "context" "crypto" "crypto/ecdsa" @@ -14,11 +15,13 @@ import ( "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/json" "fmt" "html/template" "io" + "io/ioutil" "math/big" "net/http" "net/http/httptest" @@ -29,6 +32,13 @@ import ( "time" "golang.org/x/crypto/acme" + "golang.org/x/crypto/acme/autocert/internal/acmetest" +) + +var ( + exampleDomain = "example.org" + exampleCertKey = certKey{domain: exampleDomain} + exampleCertKeyRSA = certKey{domain: exampleDomain, isRSA: true} ) var discoTmpl = template.Must(template.New("disco").Parse(`{ @@ -64,6 +74,7 @@ var authzTmpl = template.Must(template.New("authz").Parse(`{ }`)) type memCache struct { + t *testing.T mu sync.Mutex keyData map[string][]byte } @@ -79,7 +90,26 @@ func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) { return v, nil } +// filenameSafe returns whether all characters in s are printable ASCII +// and safe to use in a filename on most filesystems. +func filenameSafe(s string) bool { + for _, c := range s { + if c < 0x20 || c > 0x7E { + return false + } + switch c { + case '\\', '/', ':', '*', '?', '"', '<', '>', '|': + return false + } + } + return true +} + func (m *memCache) Put(ctx context.Context, key string, data []byte) error { + if !filenameSafe(key) { + m.t.Errorf("invalid characters in cache key %q", key) + } + m.mu.Lock() defer m.mu.Unlock() @@ -95,12 +125,29 @@ func (m *memCache) Delete(ctx context.Context, key string) error { return nil } -func newMemCache() *memCache { +func newMemCache(t *testing.T) *memCache { return &memCache{ + t: t, keyData: make(map[string][]byte), } } +func (m *memCache) numCerts() int { + m.mu.Lock() + defer m.mu.Unlock() + + res := 0 + for key := range m.keyData { + if strings.HasSuffix(key, "+token") || + strings.HasSuffix(key, "+key") || + strings.HasSuffix(key, "+http-01") { + continue + } + res++ + } + return res +} + func dummyCert(pub interface{}, san ...string) ([]byte, error) { return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...) } @@ -137,53 +184,58 @@ func decodePayload(v interface{}, r io.Reader) error { return json.Unmarshal(payload, v) } +func clientHelloInfo(sni string, ecdsaSupport bool) *tls.ClientHelloInfo { + hello := &tls.ClientHelloInfo{ + ServerName: sni, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, + } + if ecdsaSupport { + hello.CipherSuites = append(hello.CipherSuites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) + } + return hello +} + func TestGetCertificate(t *testing.T) { man := &Manager{Prompt: AcceptTOS} defer man.stopRenew() - hello := &tls.ClientHelloInfo{ServerName: "example.org"} + hello := clientHelloInfo("example.org", true) testGetCertificate(t, man, "example.org", hello) } func TestGetCertificate_trailingDot(t *testing.T) { man := &Manager{Prompt: AcceptTOS} defer man.stopRenew() - hello := &tls.ClientHelloInfo{ServerName: "example.org."} + hello := clientHelloInfo("example.org.", true) testGetCertificate(t, man, "example.org", hello) } func TestGetCertificate_ForceRSA(t *testing.T) { man := &Manager{ Prompt: AcceptTOS, - Cache: newMemCache(), + Cache: newMemCache(t), ForceRSA: true, } defer man.stopRenew() - hello := &tls.ClientHelloInfo{ServerName: "example.org"} - testGetCertificate(t, man, "example.org", hello) + hello := clientHelloInfo(exampleDomain, true) + testGetCertificate(t, man, exampleDomain, hello) - cert, err := man.cacheGet(context.Background(), "example.org") + // ForceRSA was deprecated and is now ignored. + cert, err := man.cacheGet(context.Background(), exampleCertKey) if err != nil { t.Fatalf("man.cacheGet: %v", err) } - if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok { - t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey) + if _, ok := cert.PrivateKey.(*ecdsa.PrivateKey); !ok { + t.Errorf("cert.PrivateKey is %T; want *ecdsa.PrivateKey", cert.PrivateKey) } } func TestGetCertificate_nilPrompt(t *testing.T) { man := &Manager{} defer man.stopRenew() - url, finish := startACMEServerStub(t, man, "example.org") + url, finish := startACMEServerStub(t, getCertificateFromManager(man, true), "example.org") defer finish() - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - man.Client = &acme.Client{ - Key: key, - DirectoryURL: url, - } - hello := &tls.ClientHelloInfo{ServerName: "example.org"} + man.Client = &acme.Client{DirectoryURL: url} + hello := clientHelloInfo("example.org", true) if _, err := man.GetCertificate(hello); err == nil { t.Error("got certificate for example.org; wanted error") } @@ -197,7 +249,7 @@ func TestGetCertificate_expiredCache(t *testing.T) { } tmpl := &x509.Certificate{ SerialNumber: big.NewInt(1), - Subject: pkix.Name{CommonName: "example.org"}, + Subject: pkix.Name{CommonName: exampleDomain}, NotAfter: time.Now(), } pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk) @@ -209,16 +261,16 @@ func TestGetCertificate_expiredCache(t *testing.T) { PrivateKey: pk, } - man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()} + man := &Manager{Prompt: AcceptTOS, Cache: newMemCache(t)} defer man.stopRenew() - if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil { + if err := man.cachePut(context.Background(), exampleCertKey, tlscert); err != nil { t.Fatalf("man.cachePut: %v", err) } // The expired cached cert should trigger a new cert issuance // and return without an error. - hello := &tls.ClientHelloInfo{ServerName: "example.org"} - testGetCertificate(t, man, "example.org", hello) + hello := clientHelloInfo(exampleDomain, true) + testGetCertificate(t, man, exampleDomain, hello) } func TestGetCertificate_failedAttempt(t *testing.T) { @@ -227,7 +279,6 @@ func TestGetCertificate_failedAttempt(t *testing.T) { })) defer ts.Close() - const example = "example.org" d := createCertRetryAfter f := testDidRemoveState defer func() { @@ -236,51 +287,168 @@ func TestGetCertificate_failedAttempt(t *testing.T) { }() createCertRetryAfter = 0 done := make(chan struct{}) - testDidRemoveState = func(domain string) { - if domain != example { - t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example) + testDidRemoveState = func(ck certKey) { + if ck != exampleCertKey { + t.Errorf("testDidRemoveState: domain = %v; want %v", ck, exampleCertKey) } close(done) } - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } man := &Manager{ Prompt: AcceptTOS, Client: &acme.Client{ - Key: key, DirectoryURL: ts.URL, }, } defer man.stopRenew() - hello := &tls.ClientHelloInfo{ServerName: example} + hello := clientHelloInfo(exampleDomain, true) if _, err := man.GetCertificate(hello); err == nil { t.Error("GetCertificate: err is nil") } select { case <-time.After(5 * time.Second): - t.Errorf("took too long to remove the %q state", example) + t.Errorf("took too long to remove the %q state", exampleCertKey) case <-done: man.stateMu.Lock() defer man.stateMu.Unlock() - if v, exist := man.state[example]; exist { - t.Errorf("state exists for %q: %+v", example, v) + if v, exist := man.state[exampleCertKey]; exist { + t.Errorf("state exists for %v: %+v", exampleCertKey, v) } } } +// testGetCertificate_tokenCache tests the fallback of token certificate fetches +// to cache when Manager.certTokens misses. ecdsaSupport refers to the CA when +// verifying the certificate token. +func testGetCertificate_tokenCache(t *testing.T, ecdsaSupport bool) { + man1 := &Manager{ + Cache: newMemCache(t), + Prompt: AcceptTOS, + } + defer man1.stopRenew() + man2 := &Manager{ + Cache: man1.Cache, + Prompt: AcceptTOS, + } + defer man2.stopRenew() + + // Send the verification request to a different Manager from the one that + // initiated the authorization, when they share caches. + url, finish := startACMEServerStub(t, getCertificateFromManager(man2, ecdsaSupport), "example.org") + defer finish() + man1.Client = &acme.Client{DirectoryURL: url} + hello := clientHelloInfo("example.org", true) + if _, err := man1.GetCertificate(hello); err != nil { + t.Error(err) + } + if _, err := man2.GetCertificate(hello); err != nil { + t.Error(err) + } +} + +func TestGetCertificate_tokenCache(t *testing.T) { + t.Run("ecdsaSupport=true", func(t *testing.T) { + testGetCertificate_tokenCache(t, true) + }) + t.Run("ecdsaSupport=false", func(t *testing.T) { + testGetCertificate_tokenCache(t, false) + }) +} + +func TestGetCertificate_ecdsaVsRSA(t *testing.T) { + cache := newMemCache(t) + man := &Manager{Prompt: AcceptTOS, Cache: cache} + defer man.stopRenew() + url, finish := startACMEServerStub(t, getCertificateFromManager(man, true), "example.org") + defer finish() + man.Client = &acme.Client{DirectoryURL: url} + + cert, err := man.GetCertificate(clientHelloInfo("example.org", true)) + if err != nil { + t.Error(err) + } + if _, ok := cert.Leaf.PublicKey.(*ecdsa.PublicKey); !ok { + t.Error("an ECDSA client was served a non-ECDSA certificate") + } + + cert, err = man.GetCertificate(clientHelloInfo("example.org", false)) + if err != nil { + t.Error(err) + } + if _, ok := cert.Leaf.PublicKey.(*rsa.PublicKey); !ok { + t.Error("a RSA client was served a non-RSA certificate") + } + + if _, err := man.GetCertificate(clientHelloInfo("example.org", true)); err != nil { + t.Error(err) + } + if _, err := man.GetCertificate(clientHelloInfo("example.org", false)); err != nil { + t.Error(err) + } + if numCerts := cache.numCerts(); numCerts != 2 { + t.Errorf("found %d certificates in cache; want %d", numCerts, 2) + } +} + +func TestGetCertificate_wrongCacheKeyType(t *testing.T) { + cache := newMemCache(t) + man := &Manager{Prompt: AcceptTOS, Cache: cache} + defer man.stopRenew() + url, finish := startACMEServerStub(t, getCertificateFromManager(man, true), exampleDomain) + defer finish() + man.Client = &acme.Client{DirectoryURL: url} + + // Make an RSA cert and cache it without suffix. + pk, err := rsa.GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: exampleDomain}, + NotAfter: time.Now().Add(90 * 24 * time.Hour), + } + pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk) + if err != nil { + t.Fatal(err) + } + rsaCert := &tls.Certificate{ + Certificate: [][]byte{pub}, + PrivateKey: pk, + } + if err := man.cachePut(context.Background(), exampleCertKey, rsaCert); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + + // The RSA cached cert should be silently ignored and replaced. + cert, err := man.GetCertificate(clientHelloInfo(exampleDomain, true)) + if err != nil { + t.Error(err) + } + if _, ok := cert.Leaf.PublicKey.(*ecdsa.PublicKey); !ok { + t.Error("an ECDSA client was served a non-ECDSA certificate") + } + if numCerts := cache.numCerts(); numCerts != 1 { + t.Errorf("found %d certificates in cache; want %d", numCerts, 1) + } +} + +func getCertificateFromManager(man *Manager, ecdsaSupport bool) func(string) error { + return func(sni string) error { + _, err := man.GetCertificate(clientHelloInfo(sni, ecdsaSupport)) + return err + } +} + // startACMEServerStub runs an ACME server // The domain argument is the expected domain name of a certificate request. -func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) { +// TODO: Drop this in favour of x/crypto/acme/autocert/internal/acmetest. +func startACMEServerStub(t *testing.T, getCertificate func(string) error, domain string) (url string, finish func()) { // echo token-02 | shasum -a 256 // then divide result in 2 parts separated by dot tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid" verifyTokenCert := func() { - hello := &tls.ClientHelloInfo{ServerName: tokenCertName} - _, err := man.GetCertificate(hello) - if err != nil { + if err := getCertificate(tokenCertName); err != nil { t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err) return } @@ -362,8 +530,7 @@ func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, tick := time.NewTicker(100 * time.Millisecond) defer tick.Stop() for { - hello := &tls.ClientHelloInfo{ServerName: tokenCertName} - if _, err := man.GetCertificate(hello); err != nil { + if err := getCertificate(tokenCertName); err != nil { return } select { @@ -387,21 +554,13 @@ func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, // tests man.GetCertificate flow using the provided hello argument. // The domain argument is the expected domain name of a certificate request. func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) { - url, finish := startACMEServerStub(t, man, domain) + url, finish := startACMEServerStub(t, getCertificateFromManager(man, true), domain) defer finish() - - // use EC key to run faster on 386 - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - man.Client = &acme.Client{ - Key: key, - DirectoryURL: url, - } + man.Client = &acme.Client{DirectoryURL: url} // simulate tls.Config.GetCertificate var tlscert *tls.Certificate + var err error done := make(chan struct{}) go func() { tlscert, err = man.GetCertificate(hello) @@ -445,13 +604,13 @@ func TestVerifyHTTP01(t *testing.T) { if w.Code != http.StatusOK { t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) } - if v := string(w.Body.Bytes()); !strings.HasPrefix(v, "token-http-01.") { + if v := w.Body.String(); !strings.HasPrefix(v, "token-http-01.") { t.Errorf("http token value = %q; want 'token-http-01.' prefix", v) } } // ACME CA server stub, only the needed bits. - // TODO: Merge this with startACMEServerStub, making it a configurable CA for testing. + // TODO: Replace this with x/crypto/acme/autocert/internal/acmetest. var ca *httptest.Server ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Replay-Nonce", "nonce") @@ -505,18 +664,18 @@ func TestVerifyHTTP01(t *testing.T) { })) defer ca.Close() - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } m := &Manager{ Client: &acme.Client{ - Key: key, DirectoryURL: ca.URL, }, } http01 = m.HTTPHandler(nil) - if err := m.verify(context.Background(), m.Client, "example.org"); err != nil { + ctx := context.Background() + client, err := m.acmeClient(ctx) + if err != nil { + t.Fatalf("m.acmeClient: %v", err) + } + if err := m.verify(ctx, client, "example.org"); err != nil { t.Errorf("m.verify: %v", err) } // Only tls-sni-01, tls-sni-02 and http-01 must be accepted @@ -529,6 +688,111 @@ func TestVerifyHTTP01(t *testing.T) { } } +func TestRevokeFailedAuthz(t *testing.T) { + // Prefill authorization URIs expected to be revoked. + // The challenges are selected in a specific order, + // each tried within a newly created authorization. + // This means each authorization URI corresponds to a different challenge type. + revokedAuthz := map[string]bool{ + "/authz/0": false, // tls-sni-02 + "/authz/1": false, // tls-sni-01 + "/authz/2": false, // no viable challenge, but authz is created + } + + var authzCount int // num. of created authorizations + var revokeCount int // num. of revoked authorizations + done := make(chan struct{}) // closed when revokeCount is 3 + + // ACME CA server stub, only the needed bits. + // TODO: Replace this with x/crypto/acme/autocert/internal/acmetest. + var ca *httptest.Server + ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == "HEAD" { + // a nonce request + return + } + + switch r.URL.Path { + // Discovery. + case "/": + if err := discoTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("discoTmpl: %v", err) + } + // Client key registration. + case "/new-reg": + w.Write([]byte("{}")) + // New domain authorization. + case "/new-authz": + w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount)) + w.WriteHeader(http.StatusCreated) + if err := authzTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("authzTmpl: %v", err) + } + authzCount++ + // tls-sni-02 challenge "accept" request. + case "/challenge/2": + // Refuse. + http.Error(w, "won't accept tls-sni-02 challenge", http.StatusBadRequest) + // tls-sni-01 challenge "accept" request. + case "/challenge/1": + // Accept but the authorization will be "expired". + w.Write([]byte("{}")) + // Authorization requests. + case "/authz/0", "/authz/1", "/authz/2": + // Revocation requests. + if r.Method == "POST" { + var req struct{ Status string } + if err := decodePayload(&req, r.Body); err != nil { + t.Errorf("%s: decodePayload: %v", r.URL, err) + } + switch req.Status { + case "deactivated": + revokedAuthz[r.URL.Path] = true + revokeCount++ + if revokeCount >= 3 { + // Last authorization is revoked. + defer close(done) + } + default: + t.Errorf("%s: req.Status = %q; want 'deactivated'", r.URL, req.Status) + } + w.Write([]byte(`{"status": "invalid"}`)) + return + } + // Authorization status requests. + // Simulate abandoned authorization, deleted by the CA. + w.WriteHeader(http.StatusNotFound) + default: + http.NotFound(w, r) + t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) + } + })) + defer ca.Close() + + m := &Manager{ + Client: &acme.Client{DirectoryURL: ca.URL}, + } + // Should fail and revoke 3 authorizations. + // The first 2 are tsl-sni-02 and tls-sni-01 challenges. + // The third time an authorization is created but no viable challenge is found. + // See revokedAuthz above for more explanation. + if _, err := m.createCert(context.Background(), exampleCertKey); err == nil { + t.Errorf("m.createCert returned nil error") + } + select { + case <-time.After(3 * time.Second): + t.Error("revocations took too long") + case <-done: + // revokeCount is at least 3. + } + for uri, ok := range revokedAuthz { + if !ok { + t.Errorf("%q authorization was not revoked", uri) + } + } +} + func TestHTTPHandlerDefaultFallback(t *testing.T) { tt := []struct { method, url string @@ -571,7 +835,7 @@ func TestHTTPHandlerDefaultFallback(t *testing.T) { } func TestAccountKeyCache(t *testing.T) { - m := Manager{Cache: newMemCache()} + m := Manager{Cache: newMemCache(t)} ctx := context.Background() k1, err := m.accountKey(ctx) if err != nil { @@ -587,36 +851,57 @@ func TestAccountKeyCache(t *testing.T) { } func TestCache(t *testing.T) { - privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatal(err) } - tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{CommonName: "example.org"}, - NotAfter: time.Now().Add(time.Hour), - } - pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey) + cert, err := dummyCert(ecdsaKey.Public(), exampleDomain) if err != nil { t.Fatal(err) } - tlscert := &tls.Certificate{ - Certificate: [][]byte{pub}, - PrivateKey: privKey, + ecdsaCert := &tls.Certificate{ + Certificate: [][]byte{cert}, + PrivateKey: ecdsaKey, } - man := &Manager{Cache: newMemCache()} + rsaKey, err := rsa.GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } + cert, err = dummyCert(rsaKey.Public(), exampleDomain) + if err != nil { + t.Fatal(err) + } + rsaCert := &tls.Certificate{ + Certificate: [][]byte{cert}, + PrivateKey: rsaKey, + } + + man := &Manager{Cache: newMemCache(t)} defer man.stopRenew() ctx := context.Background() - if err := man.cachePut(ctx, "example.org", tlscert); err != nil { + + if err := man.cachePut(ctx, exampleCertKey, ecdsaCert); err != nil { t.Fatalf("man.cachePut: %v", err) } - res, err := man.cacheGet(ctx, "example.org") + if err := man.cachePut(ctx, exampleCertKeyRSA, rsaCert); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + + res, err := man.cacheGet(ctx, exampleCertKey) if err != nil { t.Fatalf("man.cacheGet: %v", err) } - if res == nil { - t.Fatal("res is nil") + if res == nil || !bytes.Equal(res.Certificate[0], ecdsaCert.Certificate[0]) { + t.Errorf("man.cacheGet = %+v; want %+v", res, ecdsaCert) + } + + res, err = man.cacheGet(ctx, exampleCertKeyRSA) + if err != nil { + t.Fatalf("man.cacheGet: %v", err) + } + if res == nil || !bytes.Equal(res.Certificate[0], rsaCert.Certificate[0]) { + t.Errorf("man.cacheGet = %+v; want %+v", res, rsaCert) } } @@ -680,26 +965,28 @@ func TestValidCert(t *testing.T) { } tt := []struct { - domain string - key crypto.Signer - cert [][]byte - ok bool + ck certKey + key crypto.Signer + cert [][]byte + ok bool }{ - {"example.org", key1, [][]byte{cert1}, true}, - {"example.org", key3, [][]byte{cert3}, true}, - {"example.org", key1, [][]byte{cert1, cert2, cert3}, true}, - {"example.org", key1, [][]byte{cert1, {1}}, false}, - {"example.org", key1, [][]byte{{1}}, false}, - {"example.org", key1, [][]byte{cert2}, false}, - {"example.org", key2, [][]byte{cert1}, false}, - {"example.org", key1, [][]byte{cert3}, false}, - {"example.org", key3, [][]byte{cert1}, false}, - {"example.net", key1, [][]byte{cert1}, false}, - {"example.org", key1, [][]byte{early}, false}, - {"example.org", key1, [][]byte{expired}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{cert1}, true}, + {certKey{domain: "example.org", isRSA: true}, key3, [][]byte{cert3}, true}, + {certKey{domain: "example.org"}, key1, [][]byte{cert1, cert2, cert3}, true}, + {certKey{domain: "example.org"}, key1, [][]byte{cert1, {1}}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{{1}}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{cert2}, false}, + {certKey{domain: "example.org"}, key2, [][]byte{cert1}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{cert3}, false}, + {certKey{domain: "example.org"}, key3, [][]byte{cert1}, false}, + {certKey{domain: "example.net"}, key1, [][]byte{cert1}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{early}, false}, + {certKey{domain: "example.org"}, key1, [][]byte{expired}, false}, + {certKey{domain: "example.org", isRSA: true}, key1, [][]byte{cert1}, false}, + {certKey{domain: "example.org"}, key3, [][]byte{cert3}, false}, } for i, test := range tt { - leaf, err := validCert(test.domain, test.cert, test.key) + leaf, err := validCert(test.ck, test.cert, test.key, now) if err != nil && test.ok { t.Errorf("%d: err = %v", i, err) } @@ -748,10 +1035,155 @@ func TestManagerGetCertificateBogusSNI(t *testing.T) { {"fo.o", "cache.Get of fo.o"}, } for _, tt := range tests { - _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name}) + _, err := m.GetCertificate(clientHelloInfo(tt.name, true)) got := fmt.Sprint(err) if got != tt.wantErr { t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr) } } } + +func TestCertRequest(t *testing.T) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + // An extension from RFC7633. Any will do. + ext := pkix.Extension{ + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1}, + Value: []byte("dummy"), + } + b, err := certRequest(key, "example.org", []pkix.Extension{ext}, "san.example.org") + if err != nil { + t.Fatalf("certRequest: %v", err) + } + r, err := x509.ParseCertificateRequest(b) + if err != nil { + t.Fatalf("ParseCertificateRequest: %v", err) + } + var found bool + for _, v := range r.Extensions { + if v.Id.Equal(ext.Id) { + found = true + break + } + } + if !found { + t.Errorf("want %v in Extensions: %v", ext, r.Extensions) + } +} + +func TestSupportsECDSA(t *testing.T) { + tests := []struct { + CipherSuites []uint16 + SignatureSchemes []tls.SignatureScheme + SupportedCurves []tls.CurveID + ecdsaOk bool + }{ + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, nil, nil, false}, + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, nil, nil, true}, + + // SignatureSchemes limits, not extends, CipherSuites + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, []tls.SignatureScheme{ + tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, + }, nil, false}, + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, []tls.SignatureScheme{ + tls.PKCS1WithSHA256, + }, nil, false}, + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, []tls.SignatureScheme{ + tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, + }, nil, true}, + + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, []tls.SignatureScheme{ + tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, + }, []tls.CurveID{ + tls.CurveP521, + }, false}, + {[]uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, []tls.SignatureScheme{ + tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, + }, []tls.CurveID{ + tls.CurveP256, + tls.CurveP521, + }, true}, + } + for i, tt := range tests { + result := supportsECDSA(&tls.ClientHelloInfo{ + CipherSuites: tt.CipherSuites, + SignatureSchemes: tt.SignatureSchemes, + SupportedCurves: tt.SupportedCurves, + }) + if result != tt.ecdsaOk { + t.Errorf("%d: supportsECDSA = %v; want %v", i, result, tt.ecdsaOk) + } + } +} + +// TODO: add same end-to-end for http-01 challenge type. +func TestEndToEnd(t *testing.T) { + const domain = "example.org" + + // ACME CA server + ca := acmetest.NewCAServer([]string{"tls-alpn-01"}, []string{domain}) + defer ca.Close() + + // User dummy server. + m := &Manager{ + Prompt: AcceptTOS, + Client: &acme.Client{DirectoryURL: ca.URL}, + } + us := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("OK")) + })) + us.TLS = &tls.Config{ + NextProtos: []string{"http/1.1", acme.ALPNProto}, + GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + cert, err := m.GetCertificate(hello) + if err != nil { + t.Errorf("m.GetCertificate: %v", err) + } + return cert, err + }, + } + us.StartTLS() + defer us.Close() + // In TLS-ALPN challenge verification, CA connects to the domain:443 in question. + // Because the domain won't resolve in tests, we need to tell the CA + // where to dial to instead. + ca.Resolve(domain, strings.TrimPrefix(us.URL, "https://")) + + // A client visiting user dummy server. + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: ca.Roots, + ServerName: domain, + }, + } + client := &http.Client{Transport: tr} + res, err := client.Get(us.URL) + if err != nil { + t.Logf("CA errors: %v", ca.Errors()) + t.Fatal(err) + } + defer res.Body.Close() + b, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if v := string(b); v != "OK" { + t.Errorf("user server response: %q; want 'OK'", v) + } +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go index 61a5fd2..aa9aa84 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/cache.go +++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go @@ -16,10 +16,10 @@ import ( var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") // Cache is used by Manager to store and retrieve previously obtained certificates -// as opaque data. +// and other account data as opaque blobs. // -// The key argument of the methods refers to a domain name but need not be an FQDN. -// Cache implementations should not rely on the key naming pattern. +// Cache implementations should not rely on the key naming pattern. Keys can +// include any printable ASCII characters, except the following: \/:*?"<>| type Cache interface { // Get returns a certificate data for the specified key. // If there's no such key, Get returns ErrCacheMiss. diff --git a/vendor/golang.org/x/crypto/acme/autocert/example_test.go b/vendor/golang.org/x/crypto/acme/autocert/example_test.go index 552a625..89e2d83 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/example_test.go +++ b/vendor/golang.org/x/crypto/acme/autocert/example_test.go @@ -5,7 +5,6 @@ package autocert_test import ( - "crypto/tls" "fmt" "log" "net/http" @@ -27,10 +26,9 @@ func ExampleManager() { Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist("example.org"), } - go http.ListenAndServe(":http", m.HTTPHandler(nil)) s := &http.Server{ Addr: ":https", - TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, + TLSConfig: m.TLSConfig(), } s.ListenAndServeTLS("", "") } diff --git a/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go b/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go new file mode 100644 index 0000000..acc486a --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go @@ -0,0 +1,416 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package acmetest provides types for testing acme and autocert packages. +// +// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well. +package acmetest + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" + "net/http/httptest" + "sort" + "strings" + "sync" + "time" +) + +// CAServer is a simple test server which implements ACME spec bits needed for testing. +type CAServer struct { + URL string // server URL after it has been started + Roots *x509.CertPool // CA root certificates; initialized in NewCAServer + + rootKey crypto.Signer + rootCert []byte // DER encoding + rootTemplate *x509.Certificate + + server *httptest.Server + challengeTypes []string // supported challenge types + domainsWhitelist []string // only these domains are valid for issuing, unless empty + + mu sync.Mutex + certCount int // number of issued certs + domainAddr map[string]string // domain name to addr:port resolution + authorizations map[string]*authorization // keyed by domain name + errors []error // encountered client errors +} + +// NewCAServer creates a new ACME test server and starts serving requests. +// The returned CAServer issues certs signed with the CA roots +// available in the Roots field. +// +// The challengeTypes argument defines the supported ACME challenge types +// sent to a client in a response for a domain authorization. +// If domainsWhitelist is non-empty, the certs will be issued only for the specified +// list of domains. Otherwise, any domain name is allowed. +func NewCAServer(challengeTypes []string, domainsWhitelist []string) *CAServer { + var whitelist []string + for _, name := range domainsWhitelist { + whitelist = append(whitelist, name) + } + sort.Strings(whitelist) + ca := &CAServer{ + challengeTypes: challengeTypes, + domainsWhitelist: whitelist, + domainAddr: make(map[string]string), + authorizations: make(map[string]*authorization), + } + + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + Organization: []string{"Test Acme Co"}, + CommonName: "Root CA", + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(365 * 24 * time.Hour), + KeyUsage: x509.KeyUsageCertSign, + BasicConstraintsValid: true, + IsCA: true, + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) + if err != nil { + panic(fmt.Sprintf("x509.CreateCertificate: %v", err)) + } + cert, err := x509.ParseCertificate(der) + if err != nil { + panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) + } + ca.Roots = x509.NewCertPool() + ca.Roots.AddCert(cert) + ca.rootKey = key + ca.rootCert = der + ca.rootTemplate = tmpl + + ca.server = httptest.NewServer(http.HandlerFunc(ca.handle)) + ca.URL = ca.server.URL + return ca +} + +// Close shuts down the server and blocks until all outstanding +// requests on this server have completed. +func (ca *CAServer) Close() { + ca.server.Close() +} + +// Errors returns all client errors. +func (ca *CAServer) Errors() []error { + ca.mu.Lock() + defer ca.mu.Unlock() + return ca.errors +} + +// Resolve adds a domain to address resolution for the ca to dial to +// when validating challenges for the domain authorization. +func (ca *CAServer) Resolve(domain, addr string) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.domainAddr[domain] = addr +} + +type discovery struct { + NewReg string `json:"new-reg"` + NewAuthz string `json:"new-authz"` + NewCert string `json:"new-cert"` +} + +type challenge struct { + URI string `json:"uri"` + Type string `json:"type"` + Token string `json:"token"` +} + +type authorization struct { + Status string `json:"status"` + Challenges []challenge `json:"challenges"` + + id int + domain string +} + +func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == "HEAD" { + // a nonce request + return + } + + // TODO: Verify nonce header for all POST requests. + + switch { + default: + err := fmt.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) + ca.addError(err) + http.Error(w, err.Error(), http.StatusBadRequest) + + // Discovery request. + case r.URL.Path == "/": + resp := &discovery{ + NewReg: ca.serverURL("/new-reg"), + NewAuthz: ca.serverURL("/new-authz"), + NewCert: ca.serverURL("/new-cert"), + } + if err := json.NewEncoder(w).Encode(resp); err != nil { + panic(fmt.Sprintf("discovery response: %v", err)) + } + + // Client key registration request. + case r.URL.Path == "/new-reg": + // TODO: Check the user account key against a ca.accountKeys? + w.Write([]byte("{}")) + + // Domain authorization request. + case r.URL.Path == "/new-authz": + var req struct { + Identifier struct{ Value string } + } + if err := decodePayload(&req, r.Body); err != nil { + ca.addError(err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + ca.mu.Lock() + defer ca.mu.Unlock() + authz, ok := ca.authorizations[req.Identifier.Value] + if !ok { + authz = &authorization{ + domain: req.Identifier.Value, + Status: "pending", + } + for _, typ := range ca.challengeTypes { + authz.Challenges = append(authz.Challenges, challenge{ + Type: typ, + URI: ca.serverURL("/challenge/%s/%s", typ, authz.domain), + Token: challengeToken(authz.domain, typ), + }) + } + ca.authorizations[authz.domain] = authz + } + w.Header().Set("Location", ca.serverURL("/authz/%s", authz.domain)) + w.WriteHeader(http.StatusCreated) + if err := json.NewEncoder(w).Encode(authz); err != nil { + panic(fmt.Sprintf("new authz response: %v", err)) + } + + // Accept tls-alpn-01 challenge type requests. + // TODO: Add http-01 and dns-01 handlers. + case strings.HasPrefix(r.URL.Path, "/challenge/tls-alpn-01/"): + domain := strings.TrimPrefix(r.URL.Path, "/challenge/tls-alpn-01/") + ca.mu.Lock() + defer ca.mu.Unlock() + if _, ok := ca.authorizations[domain]; !ok { + err := fmt.Errorf("challenge accept: no authz for %q", domain) + ca.addError(err) + http.Error(w, err.Error(), http.StatusNotFound) + return + } + go func(domain string) { + err := ca.verifyALPNChallenge(domain) + ca.mu.Lock() + defer ca.mu.Unlock() + authz := ca.authorizations[domain] + if err != nil { + authz.Status = "invalid" + return + } + authz.Status = "valid" + + }(domain) + w.Write([]byte("{}")) + + // Get authorization status requests. + case strings.HasPrefix(r.URL.Path, "/authz/"): + domain := strings.TrimPrefix(r.URL.Path, "/authz/") + ca.mu.Lock() + defer ca.mu.Unlock() + authz, ok := ca.authorizations[domain] + if !ok { + http.Error(w, fmt.Sprintf("no authz for %q", domain), http.StatusNotFound) + return + } + if err := json.NewEncoder(w).Encode(authz); err != nil { + panic(fmt.Sprintf("get authz for %q response: %v", domain, err)) + } + + // Cert issuance request. + case r.URL.Path == "/new-cert": + var req struct { + CSR string `json:"csr"` + } + decodePayload(&req, r.Body) + b, _ := base64.RawURLEncoding.DecodeString(req.CSR) + csr, err := x509.ParseCertificateRequest(b) + if err != nil { + ca.addError(err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + names := unique(append(csr.DNSNames, csr.Subject.CommonName)) + if err := ca.matchWhitelist(names); err != nil { + ca.addError(err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + if err := ca.authorized(names); err != nil { + ca.addError(err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + der, err := ca.leafCert(csr) + if err != nil { + err = fmt.Errorf("new-cert response: ca.leafCert: %v", err) + ca.addError(err) + http.Error(w, err.Error(), http.StatusBadRequest) + } + w.Header().Set("Link", fmt.Sprintf("<%s>; rel=up", ca.serverURL("/ca-cert"))) + w.WriteHeader(http.StatusCreated) + w.Write(der) + + // CA chain cert request. + case r.URL.Path == "/ca-cert": + w.Write(ca.rootCert) + } +} + +func (ca *CAServer) addError(err error) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.errors = append(ca.errors, err) +} + +func (ca *CAServer) serverURL(format string, arg ...interface{}) string { + return ca.server.URL + fmt.Sprintf(format, arg...) +} + +func (ca *CAServer) matchWhitelist(dnsNames []string) error { + if len(ca.domainsWhitelist) == 0 { + return nil + } + var nomatch []string + for _, name := range dnsNames { + i := sort.SearchStrings(ca.domainsWhitelist, name) + if i == len(ca.domainsWhitelist) || ca.domainsWhitelist[i] != name { + nomatch = append(nomatch, name) + } + } + if len(nomatch) > 0 { + return fmt.Errorf("matchWhitelist: some domains don't match: %q", nomatch) + } + return nil +} + +func (ca *CAServer) authorized(dnsNames []string) error { + ca.mu.Lock() + defer ca.mu.Unlock() + var noauthz []string + for _, name := range dnsNames { + authz, ok := ca.authorizations[name] + if !ok || authz.Status != "valid" { + noauthz = append(noauthz, name) + } + } + if len(noauthz) > 0 { + return fmt.Errorf("CAServer: no authz for %q", noauthz) + } + return nil +} + +func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.certCount++ // next leaf cert serial number + leaf := &x509.Certificate{ + SerialNumber: big.NewInt(int64(ca.certCount)), + Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(90 * 24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + DNSNames: csr.DNSNames, + BasicConstraintsValid: true, + } + if len(csr.DNSNames) == 0 { + leaf.DNSNames = []string{csr.Subject.CommonName} + } + return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) +} + +func (ca *CAServer) addr(domain string) (string, error) { + ca.mu.Lock() + defer ca.mu.Unlock() + addr, ok := ca.domainAddr[domain] + if !ok { + return "", fmt.Errorf("CAServer: no addr resolution for %q", domain) + } + return addr, nil +} + +func (ca *CAServer) verifyALPNChallenge(domain string) error { + const acmeALPNProto = "acme-tls/1" + + addr, err := ca.addr(domain) + if err != nil { + return err + } + conn, err := tls.Dial("tcp", addr, &tls.Config{ + ServerName: domain, + InsecureSkipVerify: true, + NextProtos: []string{acmeALPNProto}, + }) + if err != nil { + return err + } + if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { + return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) + } + if n := len(conn.ConnectionState().PeerCertificates); n != 1 { + return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) + } + // TODO: verify conn.ConnectionState().PeerCertificates[0] + return nil +} + +func decodePayload(v interface{}, r io.Reader) error { + var req struct{ Payload string } + if err := json.NewDecoder(r).Decode(&req); err != nil { + return err + } + payload, err := base64.RawURLEncoding.DecodeString(req.Payload) + if err != nil { + return err + } + return json.Unmarshal(payload, v) +} + +func challengeToken(domain, challType string) string { + return fmt.Sprintf("token-%s-%s", domain, challType) +} + +func unique(a []string) []string { + seen := make(map[string]bool) + var res []string + for _, s := range a { + if s != "" && !seen[s] { + seen[s] = true + res = append(res, s) + } + } + return res +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go index d744df0..1e06981 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/listener.go +++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go @@ -72,11 +72,8 @@ func NewListener(domains ...string) net.Listener { // the Manager m's Prompt, Cache, HostPolicy, and other desired options. func (m *Manager) Listener() net.Listener { ln := &listener{ - m: m, - conf: &tls.Config{ - GetCertificate: m.GetCertificate, // bonus: panic on nil m - NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2 - }, + m: m, + conf: m.TLSConfig(), } ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") return ln diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go index 6c5da2b..665f870 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/renewal.go +++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go @@ -17,9 +17,9 @@ const renewJitter = time.Hour // domainRenewal tracks the state used by the periodic timers // renewing a single domain's cert. type domainRenewal struct { - m *Manager - domain string - key crypto.Signer + m *Manager + ck certKey + key crypto.Signer timerMu sync.Mutex timer *time.Timer @@ -71,25 +71,43 @@ func (dr *domainRenewal) renew() { testDidRenewLoop(next, err) } +// updateState locks and replaces the relevant Manager.state item with the given +// state. It additionally updates dr.key with the given state's key. +func (dr *domainRenewal) updateState(state *certState) { + dr.m.stateMu.Lock() + defer dr.m.stateMu.Unlock() + dr.key = state.key + dr.m.state[dr.ck] = state +} + // do is similar to Manager.createCert but it doesn't lock a Manager.state item. // Instead, it requests a new certificate independently and, upon success, // replaces dr.m.state item with a new one and updates cache for the given domain. // -// It may return immediately if the expiration date of the currently cached cert -// is far enough in the future. +// It may lock and update the Manager.state if the expiration date of the currently +// cached cert is far enough in the future. // // The returned value is a time interval after which the renewal should occur again. func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { // a race is likely unavoidable in a distributed environment // but we try nonetheless - if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil { + if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil { next := dr.next(tlscert.Leaf.NotAfter) if next > dr.m.renewBefore()+renewJitter { - return next, nil + signer, ok := tlscert.PrivateKey.(crypto.Signer) + if ok { + state := &certState{ + key: signer, + cert: tlscert.Certificate, + leaf: tlscert.Leaf, + } + dr.updateState(state) + return next, nil + } } } - der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain) + der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck) if err != nil { return 0, err } @@ -102,16 +120,15 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { if err != nil { return 0, err } - dr.m.cachePut(ctx, dr.domain, tlscert) - dr.m.stateMu.Lock() - defer dr.m.stateMu.Unlock() - // m.state is guaranteed to be non-nil at this point - dr.m.state[dr.domain] = state + if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil { + return 0, err + } + dr.updateState(state) return dr.next(leaf.NotAfter), nil } func (dr *domainRenewal) next(expiry time.Time) time.Duration { - d := expiry.Sub(timeNow()) - dr.m.renewBefore() + d := expiry.Sub(dr.m.now()) - dr.m.renewBefore() // add a bit of randomness to renew deadline n := pseudoRand.int63n(int64(renewJitter)) d -= time.Duration(n) diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go index 11d40ff..5d1c63f 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go +++ b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go @@ -23,10 +23,10 @@ import ( func TestRenewalNext(t *testing.T) { now := time.Now() - timeNow = func() time.Time { return now } - defer func() { timeNow = time.Now }() - - man := &Manager{RenewBefore: 7 * 24 * time.Hour} + man := &Manager{ + RenewBefore: 7 * 24 * time.Hour, + nowFunc: func() time.Time { return now }, + } defer man.stopRenew() tt := []struct { expiry time.Time @@ -48,8 +48,6 @@ func TestRenewalNext(t *testing.T) { } func TestRenewFromCache(t *testing.T) { - const domain = "example.org" - // ACME CA server stub var ca *httptest.Server ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -84,7 +82,7 @@ func TestRenewFromCache(t *testing.T) { if err != nil { t.Fatalf("new-cert: CSR: %v", err) } - der, err := dummyCert(csr.PublicKey, domain) + der, err := dummyCert(csr.PublicKey, exampleDomain) if err != nil { t.Fatalf("new-cert: dummyCert: %v", err) } @@ -105,30 +103,28 @@ func TestRenewFromCache(t *testing.T) { })) defer ca.Close() - // use EC key to run faster on 386 - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } man := &Manager{ Prompt: AcceptTOS, - Cache: newMemCache(), + Cache: newMemCache(t), RenewBefore: 24 * time.Hour, Client: &acme.Client{ - Key: key, DirectoryURL: ca.URL, }, } defer man.stopRenew() // cache an almost expired cert + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } now := time.Now() - cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain) + cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain) if err != nil { t.Fatal(err) } tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}} - if err := man.cachePut(context.Background(), domain, tlscert); err != nil { + if err := man.cachePut(context.Background(), exampleCertKey, tlscert); err != nil { t.Fatal(err) } @@ -152,7 +148,7 @@ func TestRenewFromCache(t *testing.T) { // ensure the new cert is cached after := time.Now().Add(future) - tlscert, err := man.cacheGet(context.Background(), domain) + tlscert, err := man.cacheGet(context.Background(), exampleCertKey) if err != nil { t.Fatalf("man.cacheGet: %v", err) } @@ -163,9 +159,9 @@ func TestRenewFromCache(t *testing.T) { // verify the old cert is also replaced in memory man.stateMu.Lock() defer man.stateMu.Unlock() - s := man.state[domain] + s := man.state[exampleCertKey] if s == nil { - t.Fatalf("m.state[%q] is nil", domain) + t.Fatalf("m.state[%q] is nil", exampleCertKey) } tlscert, err = s.tlscert() if err != nil { @@ -177,7 +173,7 @@ func TestRenewFromCache(t *testing.T) { } // trigger renew - hello := &tls.ClientHelloInfo{ServerName: domain} + hello := clientHelloInfo(exampleDomain, true) if _, err := man.GetCertificate(hello); err != nil { t.Fatal(err) } @@ -189,3 +185,145 @@ func TestRenewFromCache(t *testing.T) { case <-done: } } + +func TestRenewFromCacheAlreadyRenewed(t *testing.T) { + man := &Manager{ + Prompt: AcceptTOS, + Cache: newMemCache(t), + RenewBefore: 24 * time.Hour, + Client: &acme.Client{ + DirectoryURL: "invalid", + }, + } + defer man.stopRenew() + + // cache a recently renewed cert with a different private key + newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + now := time.Now() + newCert, err := dateDummyCert(newKey.Public(), now.Add(-2*time.Hour), now.Add(time.Hour*24*90), exampleDomain) + if err != nil { + t.Fatal(err) + } + newLeaf, err := validCert(exampleCertKey, [][]byte{newCert}, newKey, now) + if err != nil { + t.Fatal(err) + } + newTLSCert := &tls.Certificate{PrivateKey: newKey, Certificate: [][]byte{newCert}, Leaf: newLeaf} + if err := man.cachePut(context.Background(), exampleCertKey, newTLSCert); err != nil { + t.Fatal(err) + } + + // set internal state to an almost expired cert + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + oldCert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain) + if err != nil { + t.Fatal(err) + } + oldLeaf, err := validCert(exampleCertKey, [][]byte{oldCert}, key, now) + if err != nil { + t.Fatal(err) + } + man.stateMu.Lock() + if man.state == nil { + man.state = make(map[certKey]*certState) + } + s := &certState{ + key: key, + cert: [][]byte{oldCert}, + leaf: oldLeaf, + } + man.state[exampleCertKey] = s + man.stateMu.Unlock() + + // veriy the renewal accepted the newer cached cert + defer func() { + testDidRenewLoop = func(next time.Duration, err error) {} + }() + done := make(chan struct{}) + testDidRenewLoop = func(next time.Duration, err error) { + defer close(done) + if err != nil { + t.Errorf("testDidRenewLoop: %v", err) + } + // Next should be about 90 days + // Previous expiration was within 1 min. + future := 88 * 24 * time.Hour + if next < future { + t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) + } + + // ensure the cached cert was not modified + tlscert, err := man.cacheGet(context.Background(), exampleCertKey) + if err != nil { + t.Fatalf("man.cacheGet: %v", err) + } + if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { + t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) + } + + // verify the old cert is also replaced in memory + man.stateMu.Lock() + defer man.stateMu.Unlock() + s := man.state[exampleCertKey] + if s == nil { + t.Fatalf("m.state[%q] is nil", exampleCertKey) + } + stateKey := s.key.Public().(*ecdsa.PublicKey) + if stateKey.X.Cmp(newKey.X) != 0 || stateKey.Y.Cmp(newKey.Y) != 0 { + t.Fatalf("state key was not updated from cache x: %v y: %v; want x: %v y: %v", stateKey.X, stateKey.Y, newKey.X, newKey.Y) + } + tlscert, err = s.tlscert() + if err != nil { + t.Fatalf("s.tlscert: %v", err) + } + if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { + t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) + } + + // verify the private key is replaced in the renewal state + r := man.renewal[exampleCertKey] + if r == nil { + t.Fatalf("m.renewal[%q] is nil", exampleCertKey) + } + renewalKey := r.key.Public().(*ecdsa.PublicKey) + if renewalKey.X.Cmp(newKey.X) != 0 || renewalKey.Y.Cmp(newKey.Y) != 0 { + t.Fatalf("renewal private key was not updated from cache x: %v y: %v; want x: %v y: %v", renewalKey.X, renewalKey.Y, newKey.X, newKey.Y) + } + + } + + // assert the expiring cert is returned from state + hello := clientHelloInfo(exampleDomain, true) + tlscert, err := man.GetCertificate(hello) + if err != nil { + t.Fatal(err) + } + if !oldLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { + t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, oldLeaf.NotAfter) + } + + // trigger renew + go man.renew(exampleCertKey, s.key, s.leaf.NotAfter) + + // wait for renew loop + select { + case <-time.After(10 * time.Second): + t.Fatal("renew took too long to occur") + case <-done: + // assert the new cert is returned from state after renew + hello := clientHelloInfo(exampleDomain, true) + tlscert, err := man.GetCertificate(hello) + if err != nil { + t.Fatal(err) + } + if !newTLSCert.Leaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { + t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newTLSCert.Leaf.NotAfter) + } + } +} diff --git a/vendor/golang.org/x/crypto/acme/http.go b/vendor/golang.org/x/crypto/acme/http.go new file mode 100644 index 0000000..a43ce6a --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/http.go @@ -0,0 +1,281 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package acme + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "net/http" + "strconv" + "strings" + "time" +) + +// retryTimer encapsulates common logic for retrying unsuccessful requests. +// It is not safe for concurrent use. +type retryTimer struct { + // backoffFn provides backoff delay sequence for retries. + // See Client.RetryBackoff doc comment. + backoffFn func(n int, r *http.Request, res *http.Response) time.Duration + // n is the current retry attempt. + n int +} + +func (t *retryTimer) inc() { + t.n++ +} + +// backoff pauses the current goroutine as described in Client.RetryBackoff. +func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error { + d := t.backoffFn(t.n, r, res) + if d <= 0 { + return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n) + } + wakeup := time.NewTimer(d) + defer wakeup.Stop() + select { + case <-ctx.Done(): + return ctx.Err() + case <-wakeup.C: + return nil + } +} + +func (c *Client) retryTimer() *retryTimer { + f := c.RetryBackoff + if f == nil { + f = defaultBackoff + } + return &retryTimer{backoffFn: f} +} + +// defaultBackoff provides default Client.RetryBackoff implementation +// using a truncated exponential backoff algorithm, +// as described in Client.RetryBackoff. +// +// The n argument is always bounded between 1 and 30. +// The returned value is always greater than 0. +func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { + const max = 10 * time.Second + var jitter time.Duration + if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { + // Set the minimum to 1ms to avoid a case where + // an invalid Retry-After value is parsed into 0 below, + // resulting in the 0 returned value which would unintentionally + // stop the retries. + jitter = (1 + time.Duration(x.Int64())) * time.Millisecond + } + if v, ok := res.Header["Retry-After"]; ok { + return retryAfter(v[0]) + jitter + } + + if n < 1 { + n = 1 + } + if n > 30 { + n = 30 + } + d := time.Duration(1< max { + return max + } + return d +} + +// retryAfter parses a Retry-After HTTP header value, +// trying to convert v into an int (seconds) or use http.ParseTime otherwise. +// It returns zero value if v cannot be parsed. +func retryAfter(v string) time.Duration { + if i, err := strconv.Atoi(v); err == nil { + return time.Duration(i) * time.Second + } + t, err := http.ParseTime(v) + if err != nil { + return 0 + } + return t.Sub(timeNow()) +} + +// resOkay is a function that reports whether the provided response is okay. +// It is expected to keep the response body unread. +type resOkay func(*http.Response) bool + +// wantStatus returns a function which reports whether the code +// matches the status code of a response. +func wantStatus(codes ...int) resOkay { + return func(res *http.Response) bool { + for _, code := range codes { + if code == res.StatusCode { + return true + } + } + return false + } +} + +// get issues an unsigned GET request to the specified URL. +// It returns a non-error value only when ok reports true. +// +// get retries unsuccessful attempts according to c.RetryBackoff +// until the context is done or a non-retriable error is received. +func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) { + retry := c.retryTimer() + for { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + res, err := c.doNoRetry(ctx, req) + switch { + case err != nil: + return nil, err + case ok(res): + return res, nil + case isRetriable(res.StatusCode): + retry.inc() + resErr := responseError(res) + res.Body.Close() + // Ignore the error value from retry.backoff + // and return the one from last retry, as received from the CA. + if retry.backoff(ctx, req, res) != nil { + return nil, resErr + } + default: + defer res.Body.Close() + return nil, responseError(res) + } + } +} + +// post issues a signed POST request in JWS format using the provided key +// to the specified URL. +// It returns a non-error value only when ok reports true. +// +// post retries unsuccessful attempts according to c.RetryBackoff +// until the context is done or a non-retriable error is received. +// It uses postNoRetry to make individual requests. +func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) { + retry := c.retryTimer() + for { + res, req, err := c.postNoRetry(ctx, key, url, body) + if err != nil { + return nil, err + } + if ok(res) { + return res, nil + } + resErr := responseError(res) + res.Body.Close() + switch { + // Check for bad nonce before isRetriable because it may have been returned + // with an unretriable response code such as 400 Bad Request. + case isBadNonce(resErr): + // Consider any previously stored nonce values to be invalid. + c.clearNonces() + case !isRetriable(res.StatusCode): + return nil, resErr + } + retry.inc() + // Ignore the error value from retry.backoff + // and return the one from last retry, as received from the CA. + if err := retry.backoff(ctx, req, res); err != nil { + return nil, resErr + } + } +} + +// postNoRetry signs the body with the given key and POSTs it to the provided url. +// The body argument must be JSON-serializable. +// It is used by c.post to retry unsuccessful attempts. +func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { + nonce, err := c.popNonce(ctx, url) + if err != nil { + return nil, nil, err + } + b, err := jwsEncodeJSON(body, key, nonce) + if err != nil { + return nil, nil, err + } + req, err := http.NewRequest("POST", url, bytes.NewReader(b)) + if err != nil { + return nil, nil, err + } + req.Header.Set("Content-Type", "application/jose+json") + res, err := c.doNoRetry(ctx, req) + if err != nil { + return nil, nil, err + } + c.addNonce(res.Header) + return res, req, nil +} + +// doNoRetry issues a request req, replacing its context (if any) with ctx. +func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) { + res, err := c.httpClient().Do(req.WithContext(ctx)) + if err != nil { + select { + case <-ctx.Done(): + // Prefer the unadorned context error. + // (The acme package had tests assuming this, previously from ctxhttp's + // behavior, predating net/http supporting contexts natively) + // TODO(bradfitz): reconsider this in the future. But for now this + // requires no test updates. + return nil, ctx.Err() + default: + return nil, err + } + } + return res, nil +} + +func (c *Client) httpClient() *http.Client { + if c.HTTPClient != nil { + return c.HTTPClient + } + return http.DefaultClient +} + +// isBadNonce reports whether err is an ACME "badnonce" error. +func isBadNonce(err error) bool { + // According to the spec badNonce is urn:ietf:params:acme:error:badNonce. + // However, ACME servers in the wild return their versions of the error. + // See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 + // and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66. + ae, ok := err.(*Error) + return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") +} + +// isRetriable reports whether a request can be retried +// based on the response status code. +// +// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code. +// Callers should parse the response and check with isBadNonce. +func isRetriable(code int) bool { + return code <= 399 || code >= 500 || code == http.StatusTooManyRequests +} + +// responseError creates an error of Error type from resp. +func responseError(resp *http.Response) error { + // don't care if ReadAll returns an error: + // json.Unmarshal will fail in that case anyway + b, _ := ioutil.ReadAll(resp.Body) + e := &wireError{Status: resp.StatusCode} + if err := json.Unmarshal(b, e); err != nil { + // this is not a regular error response: + // populate detail with anything we received, + // e.Status will already contain HTTP response code value + e.Detail = string(b) + if e.Detail == "" { + e.Detail = resp.Status + } + } + return e.error(resp.Header) +} diff --git a/vendor/golang.org/x/crypto/acme/http_test.go b/vendor/golang.org/x/crypto/acme/http_test.go new file mode 100644 index 0000000..15e401b --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/http_test.go @@ -0,0 +1,209 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package acme + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + "time" +) + +func TestDefaultBackoff(t *testing.T) { + tt := []struct { + nretry int + retryAfter string // Retry-After header + out time.Duration // expected min; max = min + jitter + }{ + {-1, "", time.Second}, // verify the lower bound is 1 + {0, "", time.Second}, // verify the lower bound is 1 + {100, "", 10 * time.Second}, // verify the ceiling + {1, "3600", time.Hour}, // verify the header value is used + {1, "", 1 * time.Second}, + {2, "", 2 * time.Second}, + {3, "", 4 * time.Second}, + {4, "", 8 * time.Second}, + } + for i, test := range tt { + r := httptest.NewRequest("GET", "/", nil) + resp := &http.Response{Header: http.Header{}} + if test.retryAfter != "" { + resp.Header.Set("Retry-After", test.retryAfter) + } + d := defaultBackoff(test.nretry, r, resp) + max := test.out + time.Second // + max jitter + if d < test.out || max < d { + t.Errorf("%d: defaultBackoff(%v) = %v; want between %v and %v", i, test.nretry, d, test.out, max) + } + } +} + +func TestErrorResponse(t *testing.T) { + s := `{ + "status": 400, + "type": "urn:acme:error:xxx", + "detail": "text" + }` + res := &http.Response{ + StatusCode: 400, + Status: "400 Bad Request", + Body: ioutil.NopCloser(strings.NewReader(s)), + Header: http.Header{"X-Foo": {"bar"}}, + } + err := responseError(res) + v, ok := err.(*Error) + if !ok { + t.Fatalf("err = %+v (%T); want *Error type", err, err) + } + if v.StatusCode != 400 { + t.Errorf("v.StatusCode = %v; want 400", v.StatusCode) + } + if v.ProblemType != "urn:acme:error:xxx" { + t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType) + } + if v.Detail != "text" { + t.Errorf("v.Detail = %q; want text", v.Detail) + } + if !reflect.DeepEqual(v.Header, res.Header) { + t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header) + } +} + +func TestPostWithRetries(t *testing.T) { + var count int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) + if r.Method == "HEAD" { + // We expect the client to do 2 head requests to fetch + // nonces, one to start and another after getting badNonce + return + } + + head, err := decodeJWSHead(r) + switch { + case err != nil: + t.Errorf("decodeJWSHead: %v", err) + case head.Nonce == "": + t.Error("head.Nonce is empty") + case head.Nonce == "nonce1": + // Return a badNonce error to force the call to retry. + w.Header().Set("Retry-After", "0") + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`)) + return + } + // Make client.Authorize happy; we're not testing its result. + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"status":"valid"}`)) + })) + defer ts.Close() + + client := &Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}} + // This call will fail with badNonce, causing a retry + if _, err := client.Authorize(context.Background(), "example.com"); err != nil { + t.Errorf("client.Authorize 1: %v", err) + } + if count != 4 { + t.Errorf("total requests count: %d; want 4", count) + } +} + +func TestRetryErrorType(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + w.WriteHeader(http.StatusTooManyRequests) + w.Write([]byte(`{"type":"rateLimited"}`)) + })) + defer ts.Close() + + client := &Client{ + Key: testKey, + RetryBackoff: func(n int, r *http.Request, res *http.Response) time.Duration { + // Do no retries. + return 0 + }, + dir: &Directory{AuthzURL: ts.URL}, + } + + t.Run("post", func(t *testing.T) { + testRetryErrorType(t, func() error { + _, err := client.Authorize(context.Background(), "example.com") + return err + }) + }) + t.Run("get", func(t *testing.T) { + testRetryErrorType(t, func() error { + _, err := client.GetAuthorization(context.Background(), ts.URL) + return err + }) + }) +} + +func testRetryErrorType(t *testing.T, callClient func() error) { + t.Helper() + err := callClient() + if err == nil { + t.Fatal("client.Authorize returned nil error") + } + acmeErr, ok := err.(*Error) + if !ok { + t.Fatalf("err is %v (%T); want *Error", err, err) + } + if acmeErr.StatusCode != http.StatusTooManyRequests { + t.Errorf("acmeErr.StatusCode = %d; want %d", acmeErr.StatusCode, http.StatusTooManyRequests) + } + if acmeErr.ProblemType != "rateLimited" { + t.Errorf("acmeErr.ProblemType = %q; want 'rateLimited'", acmeErr.ProblemType) + } +} + +func TestRetryBackoffArgs(t *testing.T) { + const resCode = http.StatusInternalServerError + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "test-nonce") + w.WriteHeader(resCode) + })) + defer ts.Close() + + // Canceled in backoff. + ctx, cancel := context.WithCancel(context.Background()) + + var nretry int + backoff := func(n int, r *http.Request, res *http.Response) time.Duration { + nretry++ + if n != nretry { + t.Errorf("n = %d; want %d", n, nretry) + } + if nretry == 3 { + cancel() + } + + if r == nil { + t.Error("r is nil") + } + if res.StatusCode != resCode { + t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, resCode) + } + return time.Millisecond + } + + client := &Client{ + Key: testKey, + RetryBackoff: backoff, + dir: &Directory{AuthzURL: ts.URL}, + } + if _, err := client.Authorize(ctx, "example.com"); err == nil { + t.Error("err is nil") + } + if nretry != 3 { + t.Errorf("nretry = %d; want 3", nretry) + } +} diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go index 3e19974..54792c0 100644 --- a/vendor/golang.org/x/crypto/acme/types.go +++ b/vendor/golang.org/x/crypto/acme/types.go @@ -104,7 +104,7 @@ func RateLimit(err error) (time.Duration, bool) { if e.Header == nil { return 0, true } - return retryAfter(e.Header.Get("Retry-After"), 0), true + return retryAfter(e.Header.Get("Retry-After")), true } // Account is a user account. It is associated with a private key. @@ -296,8 +296,8 @@ func (e *wireError) error(h http.Header) *Error { } } -// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for -// customizing a temporary certificate for TLS-SNI challenges. +// CertOption is an optional argument type for the TLS ChallengeCert methods for +// customizing a temporary certificate for TLS-based challenges. type CertOption interface { privateCertOpt() } @@ -317,7 +317,7 @@ func (*certOptKey) privateCertOpt() {} // WithTemplate creates an option for specifying a certificate template. // See x509.CreateCertificate for template usage details. // -// In TLSSNIxChallengeCert methods, the template is also used as parent, +// In TLS ChallengeCert methods, the template is also used as parent, // resulting in a self-signed certificate. // The DNSNames field of t is always overwritten for tls-sni challenge certs. func WithTemplate(t *x509.Certificate) CertOption { diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go index 71cf8c5..b423fea 100644 --- a/vendor/golang.org/x/crypto/argon2/argon2.go +++ b/vendor/golang.org/x/crypto/argon2/argon2.go @@ -5,7 +5,35 @@ // Package argon2 implements the key derivation function Argon2. // Argon2 was selected as the winner of the Password Hashing Competition and can // be used to derive cryptographic keys from passwords. -// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// +// For a detailed specification of Argon2 see [1]. +// +// If you aren't sure which function you need, use Argon2id (IDKey) and +// the parameter recommendations for your scenario. +// +// +// Argon2i +// +// Argon2i (implemented by Key) is the side-channel resistant version of Argon2. +// It uses data-independent memory access, which is preferred for password +// hashing and password-based key derivation. Argon2i requires more passes over +// memory than Argon2id to protect from trade-off attacks. The recommended +// parameters (taken from [2]) for non-interactive operations are time=3 and to +// use the maximum available memory. +// +// +// Argon2id +// +// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining +// Argon2i and Argon2d. It uses data-independent memory access for the first +// half of the first iteration over the memory and data-dependent memory access +// for the rest. Argon2id is side-channel resistant and provides better brute- +// force cost savings due to time-memory tradeoffs than Argon2i. The recommended +// parameters for non-interactive operations (taken from [2]) are time=1 and to +// use the maximum available memory. +// +// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 package argon2 import ( @@ -25,23 +53,52 @@ const ( ) // Key derives a key from the password, salt, and cost parameters using Argon2i -// returning a byte slice of length keyLen that can be used as cryptographic key. -// The CPU cost and parallism degree must be greater than zero. +// returning a byte slice of length keyLen that can be used as cryptographic +// key. The CPU cost and parallelism degree must be greater than zero. // -// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing: -// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)` +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: // -// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024. -// The number of threads can be adjusted to the numbers of available CPUs. -// The time parameter specifies the number of passes over the memory and the memory -// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the -// memory cost to ~32 MB. -// The cost parameters should be increased as memory latency and CPU parallelism increases. -// Remember to get a good random salt. +// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) +// +// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. +// If using that amount of memory (32 MB) is not possible in some contexts then +// the time parameter can be increased to compensate. +// +// The time parameter specifies the number of passes over the memory and the +// memory parameter specifies the size of the memory in KiB. For example +// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be +// adjusted to the number of available CPUs. The cost parameters should be +// increased as memory latency and CPU parallelism increases. Remember to get a +// good random salt. func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) } +// IDKey derives a key from the password, salt, and cost parameters using +// Argon2id returning a byte slice of length keyLen that can be used as +// cryptographic key. The CPU cost and parallelism degree must be greater than +// zero. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: +// +// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) +// +// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. +// If using that amount of memory (64 MB) is not possible in some contexts then +// the time parameter can be increased to compensate. +// +// The time parameter specifies the number of passes over the memory and the +// memory parameter specifies the size of the memory in KiB. For example +// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be +// adjusted to the numbers of available CPUs. The cost parameters should be +// increased as memory latency and CPU parallelism increases. Remember to get a +// good random salt. +func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { + return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) +} + func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { if time < 1 { panic("argon2: number of rounds too small") diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go index bb2b0d8..2fc1ec0 100644 --- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go @@ -6,12 +6,11 @@ package argon2 -func init() { - useSSE4 = supportsSSE4() -} +import "golang.org/x/sys/cpu" -//go:noescape -func supportsSSE4() bool +func init() { + useSSE4 = cpu.X86.HasSSE41 +} //go:noescape func mixBlocksSSE2(out, a, b, c *block) diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s index 8a83f7c..74a6e73 100644 --- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s @@ -241,12 +241,3 @@ loop: SUBQ $2, BP JA loop RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go index 6dedb89..58ea875 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -92,6 +92,8 @@ func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } // values equal or greater than: // - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). // - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } func newDigest(hashSize int, key []byte) (*digest, error) { @@ -150,6 +152,50 @@ type digest struct { keyLen int } +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Size() int { return d.size } @@ -219,3 +265,25 @@ func (d *digest) finalize(hash *[Size]byte) { binary.LittleEndian.PutUint64(hash[8*i:], v) } } + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go index 8c41cf6..4d31dd0 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -6,21 +6,14 @@ package blake2b +import "golang.org/x/sys/cpu" + func init() { - useAVX2 = supportsAVX2() - useAVX = supportsAVX() - useSSE4 = supportsSSE4() + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - -//go:noescape -func supportsAVX() bool - -//go:noescape -func supportsAVX2() bool - //go:noescape func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) @@ -31,13 +24,14 @@ func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - if useAVX2 { + switch { + case useAVX2: hashBlocksAVX2(h, c, flag, blocks) - } else if useAVX { + case useAVX: hashBlocksAVX(h, c, flag, blocks) - } else if useSSE4 { + case useSSE4: hashBlocksSSE4(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s index 784bce6..5593b1b 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -748,15 +748,3 @@ noinc: MOVQ BP, SP RET - -// func supportsAVX2() bool -TEXT ·supportsAVX2(SB), 4, $0-1 - MOVQ runtime·support_avx2(SB), AX - MOVB AX, ret+0(FP) - RET - -// func supportsAVX() bool -TEXT ·supportsAVX(SB), 4, $0-1 - MOVQ runtime·support_avx(SB), AX - MOVB AX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go index 2ab7c30..30e2fcd 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go @@ -6,12 +6,11 @@ package blake2b -func init() { - useSSE4 = supportsSSE4() -} +import "golang.org/x/sys/cpu" -//go:noescape -func supportsSSE4() bool +func init() { + useSSE4 = cpu.X86.HasSSE41 +} //go:noescape func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s index 6453074..578e947 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -279,12 +279,3 @@ noinc: MOVQ BP, SP RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go index 5d68bbf..723327a 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go @@ -6,6 +6,7 @@ package blake2b import ( "bytes" + "encoding" "encoding/hex" "fmt" "hash" @@ -69,6 +70,54 @@ func TestHashes2X(t *testing.T) { testHashes2X(t) } +func TestMarshal(t *testing.T) { + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + for _, size := range []int{Size, Size256, Size384, 12, 25, 63} { + for i := 0; i < 256; i++ { + h, err := New(size, nil) + if err != nil { + t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) + } + h2, err := New(size, nil) + if err != nil { + t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) + } + + h.Write(input[:i/2]) + halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Fatalf("size=%d, len(input)=%d: could not marshal: %v", size, i, err) + } + err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) + if err != nil { + t.Fatalf("size=%d, len(input)=%d: could not unmarshal: %v", size, i, err) + } + + h.Write(input[i/2 : i]) + sum := h.Sum(nil) + h2.Write(input[i/2 : i]) + sum2 := h2.Sum(nil) + + if !bytes.Equal(sum, sum2) { + t.Fatalf("size=%d, len(input)=%d: results do not match; sum = %v, sum2 = %v", size, i, sum, sum2) + } + + h3, err := New(size, nil) + if err != nil { + t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) + } + h3.Write(input[:i]) + sum3 := h3.Sum(nil) + if !bytes.Equal(sum, sum3) { + t.Fatalf("size=%d, len(input)=%d: sum = %v, want %v", size, i, sum, sum3) + } + } + } +} + func testHashes(t *testing.T) { key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/golang.org/x/crypto/blake2s/blake2s.go index ae0dc92..5fb4a9e 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s.go +++ b/vendor/golang.org/x/crypto/blake2s/blake2s.go @@ -49,6 +49,8 @@ func Sum256(data []byte) [Size]byte { // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil // key turns the hash into a MAC. The key must between zero and 32 bytes long. +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } // New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a @@ -120,6 +122,50 @@ type digest struct { keyLen int } +const ( + magic = "b2s" + marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2s: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint32(b, d.h[i]) + } + b = appendUint32(b, d.c[0]) + b = appendUint32(b, d.c[1]) + // Maximum value for size is 32 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2s: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2s: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint32(b) + } + b, d.c[0] = consumeUint32(b) + b, d.c[1] = consumeUint32(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Size() int { return d.size } @@ -185,3 +231,14 @@ func (d *digest) finalize(hash *[Size]byte) { binary.LittleEndian.PutUint32(hash[4*i:], v) } } + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.go b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go index 45ae546..d8f9cea 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s_386.go +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go @@ -6,18 +6,14 @@ package blake2s +import "golang.org/x/sys/cpu" + var ( useSSE4 = false - useSSSE3 = supportSSSE3() - useSSE2 = supportSSE2() + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 ) -//go:noescape -func supportSSE2() bool - -//go:noescape -func supportSSSE3() bool - //go:noescape func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) @@ -25,11 +21,12 @@ func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { - if useSSSE3 { + switch { + case useSSSE3: hashBlocksSSSE3(h, c, flag, blocks) - } else if useSSE2 { + case useSSE2: hashBlocksSSE2(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.s b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s index 0bb65c7..c123e5d 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s_386.s +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s @@ -433,28 +433,3 @@ loop: MOVL BP, SP RET - -// func supportSSSE3() bool -TEXT ·supportSSSE3(SB), 4, $0-1 - MOVL $1, AX - CPUID - MOVL CX, BX - ANDL $0x1, BX // supports SSE3 - JZ FALSE - ANDL $0x200, CX // supports SSSE3 - JZ FALSE - MOVB $1, ret+0(FP) - RET - -FALSE: - MOVB $0, ret+0(FP) - RET - -// func supportSSE2() bool -TEXT ·supportSSE2(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $26, DX - ANDL $1, DX // DX != 0 if support SSE2 - MOVB DX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go index a925e6b..4e8d2d7 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go @@ -6,18 +6,14 @@ package blake2s +import "golang.org/x/sys/cpu" + var ( - useSSE4 = supportSSE4() - useSSSE3 = supportSSSE3() - useSSE2 = true // Always available on amd64 + useSSE4 = cpu.X86.HasSSE41 + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 ) -//go:noescape -func supportSSSE3() bool - -//go:noescape -func supportSSE4() bool - //go:noescape func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) @@ -28,13 +24,14 @@ func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { - if useSSE4 { + switch { + case useSSE4: hashBlocksSSE4(h, c, flag, blocks) - } else if useSSSE3 { + case useSSSE3: hashBlocksSSSE3(h, c, flag, blocks) - } else if useSSE2 { + case useSSE2: hashBlocksSSE2(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s index 6cdf5a9..8da2802 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s @@ -436,28 +436,3 @@ TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) RET - -// func supportSSE4() bool -TEXT ·supportSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4.1. - ANDL $1, CX - MOVB CX, ret+0(FP) - RET - -// func supportSSSE3() bool -TEXT ·supportSSSE3(SB), 4, $0-1 - MOVL $1, AX - CPUID - MOVL CX, BX - ANDL $0x1, BX // Bit zero indicates SSE3 support. - JZ FALSE - ANDL $0x200, CX // Bit nine indicates SSSE3 support. - JZ FALSE - MOVB $1, ret+0(FP) - RET - -FALSE: - MOVB $0, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_test.go b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go index cfeb18b..cde79fb 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s_test.go +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go @@ -5,6 +5,8 @@ package blake2s import ( + "bytes" + "encoding" "encoding/hex" "fmt" "testing" @@ -64,6 +66,52 @@ func TestHashes2X(t *testing.T) { testHashes2X(t) } +func TestMarshal(t *testing.T) { + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + for i := 0; i < 256; i++ { + h, err := New256(nil) + if err != nil { + t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) + } + h2, err := New256(nil) + if err != nil { + t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) + } + + h.Write(input[:i/2]) + halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Fatalf("len(input)=%d: could not marshal: %v", i, err) + } + err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) + if err != nil { + t.Fatalf("len(input)=%d: could not unmarshal: %v", i, err) + } + + h.Write(input[i/2 : i]) + sum := h.Sum(nil) + h2.Write(input[i/2 : i]) + sum2 := h2.Sum(nil) + + if !bytes.Equal(sum, sum2) { + t.Fatalf("len(input)=%d: results do not match; sum = %v, sum2 = %v", i, sum, sum2) + } + + h3, err := New256(nil) + if err != nil { + t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) + } + h3.Write(input[:i]) + sum3 := h3.Sum(nil) + if !bytes.Equal(sum, sum3) { + t.Fatalf("len(input)=%d: sum = %v, want %v", i, sum, sum3) + } + } +} + func testHashes(t *testing.T) { key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") diff --git a/vendor/golang.org/x/crypto/bn256/bn256.go b/vendor/golang.org/x/crypto/bn256/bn256.go index f88f3fc..ff27feb 100644 --- a/vendor/golang.org/x/crypto/bn256/bn256.go +++ b/vendor/golang.org/x/crypto/bn256/bn256.go @@ -97,14 +97,18 @@ func (e *G1) Neg(a *G1) *G1 { // Marshal converts n to a byte slice. func (e *G1) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if e.p.IsInfinity() { + return make([]byte, numBytes*2) + } + e.p.MakeAffine(nil) xBytes := new(big.Int).Mod(e.p.x, p).Bytes() yBytes := new(big.Int).Mod(e.p.y, p).Bytes() - // Each value is a 256-bit number. - const numBytes = 256 / 8 - ret := make([]byte, numBytes*2) copy(ret[1*numBytes-len(xBytes):], xBytes) copy(ret[2*numBytes-len(yBytes):], yBytes) @@ -205,6 +209,13 @@ func (e *G2) Add(a, b *G2) *G2 { // Marshal converts n into a byte slice. func (n *G2) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if n.p.IsInfinity() { + return make([]byte, numBytes*4) + } + n.p.MakeAffine(nil) xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() @@ -212,9 +223,6 @@ func (n *G2) Marshal() []byte { yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() - // Each value is a 256-bit number. - const numBytes = 256 / 8 - ret := make([]byte, numBytes*4) copy(ret[1*numBytes-len(xxBytes):], xxBytes) copy(ret[2*numBytes-len(xyBytes):], xyBytes) diff --git a/vendor/golang.org/x/crypto/bn256/curve.go b/vendor/golang.org/x/crypto/bn256/curve.go index 55b7063..63c052b 100644 --- a/vendor/golang.org/x/crypto/bn256/curve.go +++ b/vendor/golang.org/x/crypto/bn256/curve.go @@ -245,10 +245,19 @@ func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoi return c } +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { return c } + if c.IsInfinity() { + c.x.SetInt64(0) + c.y.SetInt64(1) + c.z.SetInt64(0) + c.t.SetInt64(0) + return c + } zInv := pool.Get().ModInverse(c.z, p) t := pool.Get().Mul(c.y, zInv) diff --git a/vendor/golang.org/x/crypto/bn256/twist.go b/vendor/golang.org/x/crypto/bn256/twist.go index 4f8b3fe..056d80f 100644 --- a/vendor/golang.org/x/crypto/bn256/twist.go +++ b/vendor/golang.org/x/crypto/bn256/twist.go @@ -219,10 +219,19 @@ func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoi return c } +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { if c.z.IsOne() { return c } + if c.IsInfinity() { + c.x.SetZero() + c.y.SetOne() + c.z.SetZero() + c.t.SetZero() + return c + } zInv := newGFp2(pool).Invert(c.z, pool) t := newGFp2(pool).Mul(c.y, zInv, pool) diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 3f0dcb9..bbb86ef 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -2,32 +2,50 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539. +// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539, +// and its extended nonce variant XChaCha20-Poly1305. package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" import ( "crypto/cipher" + "encoding/binary" "errors" ) const ( // KeySize is the size of the key used by this AEAD, in bytes. KeySize = 32 - // NonceSize is the size of the nonce used with this AEAD, in bytes. + + // NonceSize is the size of the nonce used with the standard variant of this + // AEAD, in bytes. + // + // Note that this is too short to be safely generated at random if the same + // key is reused more than 2³² times. NonceSize = 12 + + // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 + // variant of this AEAD, in bytes. + NonceSizeX = 24 ) type chacha20poly1305 struct { - key [32]byte + key [8]uint32 } -// New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key. +// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. func New(key []byte) (cipher.AEAD, error) { if len(key) != KeySize { return nil, errors.New("chacha20poly1305: bad key length") } ret := new(chacha20poly1305) - copy(ret.key[:], key) + ret.key[0] = binary.LittleEndian.Uint32(key[0:4]) + ret.key[1] = binary.LittleEndian.Uint32(key[4:8]) + ret.key[2] = binary.LittleEndian.Uint32(key[8:12]) + ret.key[3] = binary.LittleEndian.Uint32(key[12:16]) + ret.key[4] = binary.LittleEndian.Uint32(key[16:20]) + ret.key[5] = binary.LittleEndian.Uint32(key[20:24]) + ret.key[6] = binary.LittleEndian.Uint32(key[24:28]) + ret.key[7] = binary.LittleEndian.Uint32(key[28:32]) return ret, nil } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go index 7cd7ad8..ec13d13 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go @@ -6,7 +6,12 @@ package chacha20poly1305 -import "encoding/binary" +import ( + "encoding/binary" + + "golang.org/x/crypto/internal/subtle" + "golang.org/x/sys/cpu" +) //go:noescape func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool @@ -14,78 +19,27 @@ func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool //go:noescape func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) -// cpuid is implemented in chacha20poly1305_amd64.s. -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) - -// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s. -func xgetbv() (eax, edx uint32) - var ( - useASM bool - useAVX2 bool + useASM = cpu.X86.HasSSSE3 + useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 ) -func init() { - detectCPUFeatures() -} - -// detectCPUFeatures is used to detect if cpu instructions -// used by the functions implemented in assembler in -// chacha20poly1305_amd64.s are supported. -func detectCPUFeatures() { - maxID, _, _, _ := cpuid(0, 0) - if maxID < 1 { - return - } - - _, _, ecx1, _ := cpuid(1, 0) - - haveSSSE3 := isSet(9, ecx1) - useASM = haveSSSE3 - - haveOSXSAVE := isSet(27, ecx1) - - osSupportsAVX := false - // For XGETBV, OSXSAVE bit is required and sufficient. - if haveOSXSAVE { - eax, _ := xgetbv() - // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) - } - haveAVX := isSet(28, ecx1) && osSupportsAVX - - if maxID < 7 { - return - } - - _, ebx7, _, _ := cpuid(7, 0) - haveAVX2 := isSet(5, ebx7) && haveAVX - haveBMI2 := isSet(8, ebx7) - - useAVX2 = haveAVX2 && haveBMI2 -} - -// isSet checks if bit at bitpos is set in value. -func isSet(bitpos uint, value uint32) bool { - return value&(1< 0 { - alterAdIdx := mr.Intn(len(ad)) + alterAdIdx := mathrand.Intn(len(ad)) ad[alterAdIdx] ^= 0x80 if _, err := aead.Open(nil, nonce, ct, ad); err == nil { t.Errorf("#%d: Open was successful after altering additional data", i) @@ -50,14 +65,14 @@ func TestVectors(t *testing.T) { ad[alterAdIdx] ^= 0x80 } - alterNonceIdx := mr.Intn(aead.NonceSize()) + alterNonceIdx := mathrand.Intn(aead.NonceSize()) nonce[alterNonceIdx] ^= 0x80 if _, err := aead.Open(nil, nonce, ct, ad); err == nil { t.Errorf("#%d: Open was successful after altering nonce", i) } nonce[alterNonceIdx] ^= 0x80 - alterCtIdx := mr.Intn(len(ct)) + alterCtIdx := mathrand.Intn(len(ct)) ct[alterCtIdx] ^= 0x80 if _, err := aead.Open(nil, nonce, ct, ad); err == nil { t.Errorf("#%d: Open was successful after altering ciphertext", i) @@ -68,87 +83,117 @@ func TestVectors(t *testing.T) { func TestRandom(t *testing.T) { // Some random tests to verify Open(Seal) == Plaintext - for i := 0; i < 256; i++ { - var nonce [12]byte - var key [32]byte + f := func(t *testing.T, nonceSize int) { + for i := 0; i < 256; i++ { + var nonce = make([]byte, nonceSize) + var key [32]byte - al := mr.Intn(128) - pl := mr.Intn(16384) - ad := make([]byte, al) - plaintext := make([]byte, pl) - cr.Read(key[:]) - cr.Read(nonce[:]) - cr.Read(ad) - cr.Read(plaintext) + al := mathrand.Intn(128) + pl := mathrand.Intn(16384) + ad := make([]byte, al) + plaintext := make([]byte, pl) + cryptorand.Read(key[:]) + cryptorand.Read(nonce[:]) + cryptorand.Read(ad) + cryptorand.Read(plaintext) - aead, err := New(key[:]) - if err != nil { - t.Fatal(err) - } - - ct := aead.Seal(nil, nonce[:], plaintext, ad) - - plaintext2, err := aead.Open(nil, nonce[:], ct, ad) - if err != nil { - t.Errorf("Random #%d: Open failed", i) - continue - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) - continue - } - - if len(ad) > 0 { - alterAdIdx := mr.Intn(len(ad)) - ad[alterAdIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering additional data", i) + var ( + aead cipher.AEAD + err error + ) + switch len(nonce) { + case NonceSize: + aead, err = New(key[:]) + case NonceSizeX: + aead, err = NewX(key[:]) + default: + t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce)) + } + if err != nil { + t.Fatal(err) } - ad[alterAdIdx] ^= 0x80 - } - alterNonceIdx := mr.Intn(aead.NonceSize()) - nonce[alterNonceIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering nonce", i) - } - nonce[alterNonceIdx] ^= 0x80 + ct := aead.Seal(nil, nonce[:], plaintext, ad) - alterCtIdx := mr.Intn(len(ct)) - ct[alterCtIdx] ^= 0x80 - if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { - t.Errorf("Random #%d: Open was successful after altering ciphertext", i) + plaintext2, err := aead.Open(nil, nonce[:], ct, ad) + if err != nil { + t.Errorf("Random #%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + alterAdIdx := mathrand.Intn(len(ad)) + ad[alterAdIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering additional data", i) + } + ad[alterAdIdx] ^= 0x80 + } + + alterNonceIdx := mathrand.Intn(aead.NonceSize()) + nonce[alterNonceIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering nonce", i) + } + nonce[alterNonceIdx] ^= 0x80 + + alterCtIdx := mathrand.Intn(len(ct)) + ct[alterCtIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering ciphertext", i) + } + ct[alterCtIdx] ^= 0x80 } - ct[alterCtIdx] ^= 0x80 } + t.Run("Standard", func(t *testing.T) { f(t, NonceSize) }) + t.Run("X", func(t *testing.T) { f(t, NonceSizeX) }) } -func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte) { +func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { + b.ReportAllocs() b.SetBytes(int64(len(buf))) var key [32]byte - var nonce [12]byte + var nonce = make([]byte, nonceSize) var ad [13]byte var out []byte - aead, _ := New(key[:]) + var aead cipher.AEAD + switch len(nonce) { + case NonceSize: + aead, _ = New(key[:]) + case NonceSizeX: + aead, _ = NewX(key[:]) + } + b.ResetTimer() for i := 0; i < b.N; i++ { out = aead.Seal(out[:0], nonce[:], buf[:], ad[:]) } } -func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) { +func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { + b.ReportAllocs() b.SetBytes(int64(len(buf))) var key [32]byte - var nonce [12]byte + var nonce = make([]byte, nonceSize) var ad [13]byte var ct []byte var out []byte - aead, _ := New(key[:]) + var aead cipher.AEAD + switch len(nonce) { + case NonceSize: + aead, _ = New(key[:]) + case NonceSizeX: + aead, _ = NewX(key[:]) + } ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:]) b.ResetTimer() @@ -157,26 +202,54 @@ func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) { } } -func BenchmarkChacha20Poly1305Open_64(b *testing.B) { - benchamarkChaCha20Poly1305Open(b, make([]byte, 64)) +func BenchmarkChacha20Poly1305(b *testing.B) { + for _, length := range []int{64, 1350, 8 * 1024} { + b.Run("Open-"+strconv.Itoa(length), func(b *testing.B) { + benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize) + }) + b.Run("Seal-"+strconv.Itoa(length), func(b *testing.B) { + benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize) + }) + + b.Run("Open-"+strconv.Itoa(length)+"-X", func(b *testing.B) { + benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX) + }) + b.Run("Seal-"+strconv.Itoa(length)+"-X", func(b *testing.B) { + benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX) + }) + } } -func BenchmarkChacha20Poly1305Seal_64(b *testing.B) { - benchamarkChaCha20Poly1305Seal(b, make([]byte, 64)) -} +var key = make([]byte, KeySize) -func BenchmarkChacha20Poly1305Open_1350(b *testing.B) { - benchamarkChaCha20Poly1305Open(b, make([]byte, 1350)) -} +func ExampleNewX() { + aead, err := NewX(key) + if err != nil { + log.Fatalln("Failed to instantiate XChaCha20-Poly1305:", err) + } -func BenchmarkChacha20Poly1305Seal_1350(b *testing.B) { - benchamarkChaCha20Poly1305Seal(b, make([]byte, 1350)) -} + for _, msg := range []string{ + "Attack at dawn.", + "The eagle has landed.", + "Gophers, gophers, gophers everywhere!", + } { + // Encryption. + nonce := make([]byte, NonceSizeX) + if _, err := cryptorand.Read(nonce); err != nil { + panic(err) + } + ciphertext := aead.Seal(nil, nonce, []byte(msg), nil) -func BenchmarkChacha20Poly1305Open_8K(b *testing.B) { - benchamarkChaCha20Poly1305Open(b, make([]byte, 8*1024)) -} + // Decryption. + plaintext, err := aead.Open(nil, nonce, ciphertext, nil) + if err != nil { + log.Fatalln("Failed to decrypt or authenticate message:", err) + } -func BenchmarkChacha20Poly1305Seal_8K(b *testing.B) { - benchamarkChaCha20Poly1305Seal(b, make([]byte, 8*1024)) + fmt.Printf("%s\n", plaintext) + } + + // Output: Attack at dawn. + // The eagle has landed. + // Gophers, gophers, gophers everywhere! } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go index 49f0da6..fa3607e 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go @@ -7,6 +7,13 @@ package chacha20poly1305 var chacha20Poly1305Tests = []struct { plaintext, aad, key, nonce, out string }{ + { + "", + "", + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + "a0784d7a4716f3feb4f64e7f4b39bf04", + }, { "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", "50515253c0c1c2c3c4c5c6c7", @@ -329,4 +336,391 @@ var chacha20Poly1305Tests = []struct { "129039b5572e8a7a8131f76a", "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", }, + + // XChaCha20-Poly1305 vectors + { + "000000000000000000000000000000", + "", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000", + "789e9689e5208d7fd9e1f3c5b5341fb2f7033812ac9ebd3745e2c99c7bbfeb", + }, + { + "02dc819b71875e49f5e1e5a768141cfd3f14307ae61a34d81decd9a3367c00c7", + "", + "b7bbfe61b8041658ddc95d5cbdc01bbe7626d24f3a043b70ddee87541234cff7", + "e293239d4c0a07840c5f83cb515be7fd59c333933027e99c", + "7a51f271bd2e547943c7be3316c05519a5d16803712289aa2369950b1504dd8267222e47b13280077ecada7b8795d535", + }, + { + "7afc5f3f24155002e17dc176a8f1f3a097ff5a991b02ff4640f70b90db0c15c328b696d6998ea7988edfe3b960e47824e4ae002fbe589be57896a9b7bf5578599c6ba0153c7c", + "d499bb9758debe59a93783c61974b7", + "4ea8fab44a07f7ffc0329b2c2f8f994efdb6d505aec32113ae324def5d929ba1", + "404d5086271c58bf27b0352a205d21ce4367d7b6a7628961", + "26d2b46ad58b6988e2dcf1d09ba8ab6f532dc7e0847cdbc0ed00284225c02bbdb278ee8381ebd127a06926107d1b731cfb1521b267168926492e8f77219ad922257a5be2c5e52e6183ca4dfd0ad3912d7bd1ec968065", + }, + { + "", + "", + "48d8bd02c2e9947eae58327114d35e055407b5519c8019535efcb4fc875b5e2b", + "cc0a587a475caba06f8dbc09afec1462af081fe1908c2cba", + "fc3322d0a9d6fac3eb4a9e09b00b361e", + }, + { + "e0862731e5", + "", + "6579e7ee96151131a1fcd06fe0d52802c0021f214960ecceec14b2b8591f62cd", + "e2230748649bc22e2b71e46a7814ecabe3a7005e949bd491", + "e991efb85d8b1cfa3f92cb72b8d3c882e88f4529d9", + }, + { + "00c7dd8f440af1530b44", + "", + "ffb733657c849d50ab4ab40c4ae18f8ee2f0acf7c907afefdc04dff3537fdff3", + "02c6fd8032a8d89edbedcd1db024c09d29f08b1e74325085", + "13dbcdb8c60c3ed28449a57688edfaea89e309ab4faa6d51e532", + }, + { + "7422f311ea476cf819cb8b3c77369f", + "", + "ef0d05d028d6abdd5e99d1761d2028de75ee6eb376ff0dc8036e9a8e10743876", + "f772745200b0f92e38f1d8dae79bf8138e84b301f0be74df", + "d5f992f9834df1be86b580ac59c7eae063a68072829c51bc8a26970dd3d310", + }, + { + "ba09ca69450e6c7bece31a7a3f216e3b9ed0e536", + "", + "8d93e31abfe22a63faf45cbea91877050718f13fef6e2664a1892d7f23007ccf", + "260b7b3554a7e6ff8aae7dd6234077ca539689a20c1610a8", + "c99e9a768eb2ec8569bdff8a37295069552faebcafb1a76e98bc7c5b6b778b3d1b6291f0", + }, + { + "424ec5f98a0fdc5a7388532d11ab0edb26733505627b7f2d1f", + "", + "b68d5e6c46cdbb0060445522bdc5c562ae803b6aaaf1e103c146e93527a59299", + "80bb5dc1dd44a35ec4f91307f1a95b4ca31183a1a596fb7c", + "29d4eed0fff0050d4bb40de3b055d836206e7cbd62de1a63904f0cf731129ba3f9c2b9d46251a6de89", + }, + { + "e7e4515cc0a6ef0491af983eaac4f862d6e726758a3c657f4ec444841e42", + "", + "e31a1d3af650e8e2848bd78432d89ecd1fdece9842dc2792e7bda080f537b17b", + "f3f09905e9a871e757348834f483ed71be9c0f437c8d74b0", + "f5c69528963e17db725a28885d30a45194f12848b8b7644c7bded47a2ee83e6d4ef34006305cfdf82effdced461d", + }, + { + "0f5ca45a54875d1d19e952e53caeaa19389342f776dab11723535503338d6f77202a37", + "", + "1031bc920d4fcb4434553b1bf2d25ab375200643bf523ff037bf8914297e8dca", + "4cc77e2ef5445e07b5f44de2dc5bf62d35b8c6f69502d2bf", + "7aa8669e1bfe8b0688899cdddbb8cee31265928c66a69a5090478da7397573b1cc0f64121e7d8bff8db0ddd3c17460d7f29a12", + }, + { + "c45578c04c194994e89025c7ffb015e5f138be3cd1a93640af167706aee2ad25ad38696df41ad805", + "", + "ac8648b7c94328419c668ce1c57c71893adf73abbb98892a4fc8da17400e3a5e", + "4ad637facf97af5fc03207ae56219da9972858b7430b3611", + "49e093fcd074fb67a755669119b8bd430d98d9232ca988882deeb3508bde7c00160c35cea89092db864dcb6d440aefa5aacb8aa7b9c04cf0", + }, + { + "b877bfa192ea7e4c7569b9ee973f89924d45f9d8ed03c7098ad0cad6e7880906befedcaf6417bb43efabca7a2f", + "", + "125e331d5da423ecabc8adf693cdbc2fc3d3589740d40a3894f914db86c02492", + "913f8b2f08006e6260de41ec3ee01d938a3e68fb12dc44c4", + "1be334253423c90fc8ea885ee5cd3a54268c035ba8a2119e5bd4f7822cd7bf9cb4cec568d5b6d6292606d32979e044df3504e6eb8c0b2fc7e2a0e17d62", + }, + { + "d946484a1df5f85ff72c92ff9e192660cde5074bd0ddd5de900c35eb10ed991113b1b19884631bc8ceb386bcd83908061ce9", + "", + "b7e83276373dcf8929b6a6ea80314c9de871f5f241c9144189ee4caf62726332", + "f59f9d6e3e6c00720dc20dc21586e8330431ebf42cf9180e", + "a38a662b18c2d15e1b7b14443cc23267a10bee23556b084b6254226389c414069b694159a4d0b5abbe34de381a0e2c88b947b4cfaaebf50c7a1ad6c656e386280ad7", + }, + { + "d266927ca40b2261d5a4722f3b4da0dd5bec74e103fab431702309fd0d0f1a259c767b956aa7348ca923d64c04f0a2e898b0670988b15e", + "", + "a60e09cd0bea16f26e54b62b2908687aa89722c298e69a3a22cf6cf1c46b7f8a", + "92da9d67854c53597fc099b68d955be32df2f0d9efe93614", + "9dd6d05832f6b4d7f555a5a83930d6aed5423461d85f363efb6c474b6c4c8261b680dea393e24c2a3c8d1cc9db6df517423085833aa21f9ab5b42445b914f2313bcd205d179430", + }, + { + "f7e11b4d372ed7cb0c0e157f2f9488d8efea0f9bbe089a345f51bdc77e30d1392813c5d22ca7e2c7dfc2e2d0da67efb2a559058d4de7a11bd2a2915e", + "", + "194b1190fa31d483c222ec475d2d6117710dd1ac19a6f1a1e8e894885b7fa631", + "6b07ea26bb1f2d92e04207b447f2fd1dd2086b442a7b6852", + "25ae14585790d71d39a6e88632228a70b1f6a041839dc89a74701c06bfa7c4de3288b7772cb2919818d95777ab58fe5480d6e49958f5d2481431014a8f88dab8f7e08d2a9aebbe691430011d", + }, + { + "", + "1e2b11e3", + "70cd96817da85ede0efdf03a358103a84561b25453dee73735e5fb0161b0d493", + "5ddeba49f7266d11827a43931d1c300dd47a3c33f9f8bf9b", + "592fc4c19f3cddec517b2a00f9df9665", + }, + { + "81b3cb7eb3", + "efcfd0cf", + "a977412f889281a6d75c24186f1bfaa00dcc5132f0929f20ef15bbf9e63c4c91", + "3f26ca997fb9166d9c615babe3e543ca43ab7cab20634ac5", + "8e4ade3e254cf52e93eace5c46667f150832725594", + }, + { + "556f97f2ebdb4e949923", + "f7cee2e0", + "787b3e86546a51028501c801dadf8d5b996fd6f6f2363d5d0f900c44f6a2f4c2", + "7fa6af59a779657d1cada847439ea5b92a1337cfbebbc3b1", + "608ec22dae5f48b89d6f0d2a940d5a7661e0a8e68aaee4ad2d96", + }, + { + "c06847a36ad031595b60edd44dc245", + "d4175e1f", + "16de31e534dd5af32801b1acd0ec541d1f8d82bcbc3af25ec815f3575b7aca73", + "29f6656972838f56c1684f6a278f9e4e207b51d68706fc25", + "836082cc51303e500fceade0b1a18f1d97d64ff41cc81754c07d6231b9fd1b", + }, + { + "0d03c22ced7b29c6741e72166cd61792028dfc80", + "e505dad0", + "ac2b426e5c5c8e00666180a3410e8a2f6e52247a43aecea9622163e8433c93b2", + "c1123430468228625967bbc0fbd0f963e674372259ff2deb", + "bf09979bf4fed2eec6c97f6e1bcfac35eeffc6d54a55cc1d83d8767ae74db2d7cdfbc371", + }, + { + "05bf00e1707cffe7ccbd06a9f846d0fd471a700ed43b4facb8", + "d863bebe", + "66c121f0f84b95ba1e6d29e7d81900bc96a642421b9b6105ae5eb5f2e7b07577", + "8ed6ae211a661e967995b71f7316ba88f44322bb62b4187b", + "b2c5c85d087e0305e9058fba52b661fb3d7f21cb4d4915ae048bc9e5d66a2f921dd4a1c1b030f442c9", + }, + { + "5f2b91a9be8bfaa21451ddc6c5cf28d1cc00b046b76270b95cda3c280c83", + "a8750275", + "39592eb276877fca9dd11e2181c0b23127328407e3cc11e315e5d748f43529cc", + "1084bebd756f193d9eea608b3a0193a5028f8ced19684821", + "eaee1f49ac8468154c601a5dd8b84d597602e5a73534b5fad5664f97d0f017dd114752be969679cf610340c6a312", + }, + { + "01e8e269b5376943f3b2d245483a76461dc8b7634868b559165f5dbb20839029fae9bb", + "a1e96da0", + "b8386123b87e50d9d046242cf1bf141fce7f65aff0fba76861a2bc72582d6ff0", + "0fbe2a13a89bea031de96d78f9f11358ba7b6a5e724b4392", + "705ec3f910ec85c6005baa99641de6ca43332ff52b5466df6af4ffbe4ef2a376a8f871d1eae503b5896601fee005cdc1f4c1c6", + }, + { + "706daba66e2edb1f828f3c0051e3cc214b12210bde0587bba02580f741a4c83e84d4e9fe961120cd", + "87663c5a", + "d519d82ba8a3f0c3af9efe36682b62e285167be101a526c1d73000f169c2a486", + "ad651aac536978e2bc1a54816345ac5e9a9b43b3d9cc0bfc", + "07051b5e72da9c4811beb07ff9f95aece67eae18420eb3f0e8bb8a5e26d4b483fa40eb063a2354842d0c8a41d981cc2b77c530b496db01c8", + }, + { + "1f6b24f2f0d9eb460d726bed953d66fcc4ecc29da6ed2fd711358eac3b2609d74ba3e21885156cde3cbe6d9b6f", + "f5efbc4e", + "86068a00544f749ad4ad15bb8e427ae78577ae22f4ca9778efff828ba10f6b20", + "c8420412c9626dcd34ece14593730f6aa2d01ec51cacd59f", + "a99f6c88eac35bb34439e34b292fe9db8192446dcdc81e2192060ec36d98b47de2bee12bf0f67cb24fb0949c07733a6781cd9455cdc61123f506886b04", + }, + { + "d69389d83362be8c0ddb738659a6cc4bd65d88cb5b525232f4d59a7d4751a7203c254923ecb6873e803220aab19664789a63", + "bc35fb1c", + "835855b326a98682b3075b4d7f1b89059c3cdfc547d4296c80ce7a77ba6434e3", + "c27cb75fc319ba431cbaeb120341d0c4745d883eb47e92bc", + "db6dc3f9a0f4f1a6df2495a88910550c2c6205478bfc1e81282e34b5b36d984c72c0509c522c987c61d2e640ced69402a6d33aa10d3d0b81e680b3c19bc142e81923", + }, + { + "a66a7f089115ed9e2d5bb5d33d7282a7afe401269b00f2a233a59c04b794a42901d862140b61d18d7c7f0ad5da040613e557f8abc74219", + "2c060aaf", + "99758aa7714fd707931f71803eefe04a06955041308a0b2a1104313b270ccf34", + "63f690d8926408c7a34fe8ddd505a8dc58769dc74e8d5da6", + "92b21ee85afcd8996ac28f3aed1047ad814d6e4ffbca3159af16f26eded83e4abda9e4275eb3ff0ad90dffe09f2d443b628f824f680b46527ce0128e8de1920f7c44350ebe7913", + }, + { + "f955183b1f762d4536d3f6885ea7f5ac27414caf46c2e24a2fd3bd56b91c53d840fb657224565e0a6f686f8ba320e04a401057399d9a3d995ab17c13", + "c372ddc5", + "a188be3795b2ca2e69b6aa263244f0963c492d694cf6c9b705a1d7045f3f2a26", + "51bb484ea094ee140474681e1c838e4442fd148de2cc345a", + "48759a5ddfdd829d11de8e0c538ce4a9c475faab6912039b568ad92d737d172fc1eb0c00c3793de6dddbfacfdbbc7f44aeba33684e18005aa982b6fc6c556e63bb90ff7a1dde8153a63eabe0", + }, + { + "", + "e013cd0bfafd486d", + "af3d3ba094d38299ecb91c17bfe3d085da5bd42e11acf8acb5bc26a4be9a7583", + "7dd63c14173831f109761b1c1abe18f6ba937d825957011b", + "8bc685a7d9d501952295cd25d8c92517", + }, + { + "284b64597e", + "31d013e53aa3ea79", + "93c77409d7f805f97fe683b2dd6ee06152a5e918b3eed5b731acccffdcb2cc04", + "3d331e90c4597cf0c30d1b7cfbd07bcb6ab927eda056873c", + "3538a449d6c18d148a8c6cb76f1bc288657ac7036a", + }, + { + "9fe67f5c78180ede8274", + "188608d230d75860", + "b7cca89a82640aea6f80b458c9e633d88594fb498959d39787be87030892d48f", + "ef891d50e8c08958f814590fdb7a9f16c61cc2aae1682109", + "bbb40c30f3d1391a5b38df480cbbf964b71e763e8140751f4e28", + }, + { + "3a2826b6f7e3d542e4ded8f23c9aa4", + "260033e789c4676a", + "7fe2731214f2b4b42f93217d43f1776498413725e4f6cfe62b756e5a52df10ea", + "888728219ebf761547f5e2218532714403020e5a8b7a49d0", + "fe0328f883fcd88930ae017c0f54ed90f883041efc020e959125af370c1d47", + }, + { + "91858bf7b969005d7164acbd5678052b651c53e0", + "f3cc53ecafcbadb3", + "d69c04e9726b22d51f97bc9da0f0fda86736e6b78e8ef9f6f0000f79890d6d43", + "6de3c45161b434e05445cf6bf69eef7bddf595fc6d8836bd", + "a8869dd578c0835e120c843bb7dedc7a1e9eae24ffd742be6bf5b74088a8a2c550976fcb", + }, + { + "b3b1a4d6b2a2b9c5a1ca6c1efaec34dcfa1acbe7074d5e10cc", + "d0f72bd16cda3bae", + "2b317857b089c9305c49b83019f6e158bc4ecc3339b39ade02ee10c37c268da0", + "cb5fa6d1e14a0b4bdf350cd10c8a7bd638102911ec74be09", + "e6372f77c14343650074e07a2b7223c37b29242224b722b24d63b5956f27aa64ce7ce4e39cd14a2787", + }, + { + "057d3e9f865be7dff774938cab6d080e50cf9a1593f53c0063201e0bb7ae", + "fd3881e505c8b12d", + "36e42b1ef1ee8d068f09b5fad3ee43d98d34aa3e3f994f2055aee139da71de9d", + "24124da36473d01bdca30297c9eef4fe61955525a453da17", + "a8b28139524c98c1f8776f442eac4c22766fe6aac83224641c58bf021fc9cb709ec4706f49c2d0c1828acf2bfe8d", + }, + { + "bd8f13e928c34d67a6c70c3c7efdf2982ecc31d8cee68f9cbddc75912cd828ac93d28b", + "193206c8fcc5b19b", + "6e47c40c9d7b757c2efca4d73890e4c73f3c859aab4fdc64b564b8480dd84e72", + "ca31340ae20d30fe488be355cb36652c5db7c9d6265a3e95", + "a121efc5e1843deade4b8adbfef1808de4eda222f176630ad34fb476fca19e0299e4a13668e53cf13882035ba4f04f47c8b4e3", + }, + { + "23067a196e977d10039c14ff358061c918d2148d31961bb3e12c27c5122383cb25c4d1d79c775720", + "62338d02fff78a00", + "2c5c79c92d91fb40ef7d0a77e8033f7b265e3bab998b8116d17b2e62bb4f8a09", + "024736adb1d5c01006dffd8158b57936d158d5b42054336d", + "46d0905473a995d38c7cdbb8ef3da96ecc82a22c5b3c6c9d1c4a61ae7a17db53cb88c5f7eccf2da1d0c417c300f989b4273470e36f03542f", + }, + { + "252e966c680329eb687bff813b78fea3bfd3505333f106c6f9f45ba69896723c41bb763793d9b266e897d05557", + "1e93e0cfe6523380", + "9ec6fd1baa13ee16aec3fac16718a2baccf18a403cec467c25b7448e9b321110", + "e7120b1018ab363a36e61102eedbcbe9847a6cbacaa9c328", + "2934f034587d4144bb11182679cd2cd1c99c8088d18e233379e9bc9c41107a1f57a2723ecc7b9ba4e6ee198adf0fd766738e828827dc73136fc5b996e9", + }, + { + "6744aefcb318f12bc6eeb59d4d62f7eb95f347cea14bd5158415f07f84e4e3baa3de07512d9b76095ac1312cfcb1bb77f499", + "608d2a33ce5d0b04", + "0f665cbdaaa40f4f5a00c53d951b0a98aac2342be259a52670f650a783be7aab", + "378bdb57e957b8c2e1500c9513052a3b02ff5b7edbd4a3a7", + "341c60fcb374b394f1b01a4a80aedef49ab0b67ec963675e6eec43ef106f7003be87dbf4a8976709583dccc55abc7f979c4721837e8664a69804ea31736aa2af615a", + }, + { + "bcf1004f988220b7ce063ef2ec4e276ffd074f0a90aa807de1532679d2a1505568eaa4192d9a6ea52cc500322343ce9f8e68cc2c606d83", + "e64bd00126c8792c", + "58e65150d6a15dcefbc14a171998987ad0d709fb06a17d68d6a778759681c308", + "106d2bd120b06e4eb10bc674fe55c77a3742225268319303", + "a28052a6686a1e9435fee8702f7da563a7b3d7b5d3e9e27f11abf73db309cd1f39a34756258c1c5c7f2fb12cf15eb20175c2a08fc93dd19c5e482ef3fbef3d8404a3cfd54a7baf", + }, + { + "acd08d4938a224b4cb2d723bf75420f3ea27b698fadd815bb7db9548a05651398644354334e69f8e4e5503bf1a6f92b38e860044a7edca6874038ce1", + "28a137808d0225b8", + "a031203b963a395b08be55844d81af39d19b23b7cc24b21afa31edc1eea6edd6", + "e8b31c52b6690f10f4ae62ba9d50ba39fb5edcfb78400e35", + "35cf39ba31da95ac9b661cdbd5e9c9655d13b8ff065c4ec10c810833a47a87d8057dd1948a7801bfe6904b49fed0aabfb3cd755a1a262d372786908ddcf64cae9f71cb9ed199c3ddacc50116", + }, + { + "", + "cda7ee2857e09e9054ef6806", + "d91dffb18132d8dd3d144a2f10ba28bc5df36cb60369f3b19893ec91db3cf904", + "ee56f19c62b0438da6a0d9e01844313902be44f84a6a4ce7", + "ccd48b61a5683c195d4424009eb1d147", + }, + { + "350f4c7ac2", + "7c104b539c1d2ae022434cd6", + "cbb61e369117f9250f68fa707240c554359262a4d66c757f80e3aeb6920894fb", + "fbb14c9943444eac5413c6f5c8095451eddece02c9461043", + "b5c6a35865ed8e5216ff6c77339ee1ab570de50e51", + }, + { + "4f0d61d3ea03a44a8df0", + "51c20a8ae9e9794da931fe23", + "ba6ced943aa62f9261d7513b822e02054e099acafb5360f0d850064da48b5a4f", + "04c68cb50cdbb0ec03f8381cf59b886e64c40548bf8e3f82", + "ea45a73957e2a853655623f2a3bb58791f7ea36dd2957ed66ffa", + }, + { + "4fbdd4d4293a8f34fdbc8f3ad44cf6", + "8212f315e3759c3253c588bb", + "5354791bc2370415811818e913e310dd12e6a0cf5dcab2b6424816eecccf4b65", + "7ee6353c2fbc73c9ebc652270bc86e4008e09583e623e679", + "50a354811a918e1801fb567621a8924baf8dd79da6d36702855d3753f1319c", + }, + { + "5a6f68b5a9a9920ca9c6edf5be7c0af150a063c4", + "9a524aa62938fb7a1e50ed06", + "fd91605a6ad85d8ba7a71b08dce1032aa9992bf4f28d407a53ddda04c043cada", + "46791d99d6de33e79025bf9e97c198e7cf409614c6284b4d", + "648033c1eb615467e90b7d3ac24202d8b849549141f9bab03e9e910c29b8eab3d4fb3f2c", + }, + { + "d9318c2c0d9ed89e35d242a6b1d496e7e0c5bbdf77eba14c56", + "a16053c35fbe8dc93c14a81f", + "f21406aec83134ebf7bc48c6d0f45acb5f341fbc7d3b5a9bff3ea1333c916af7", + "de6b977be450d5efa7777e006802ddbb10814a22da1c3cd9", + "8d3dad487d5161663da830b71c3e24ec5cdb74d858cbb73b084ed0902198532aad3a18416966bff223", + }, + { + "68d0ee08d38cb4bcc9268fee3030666e70e41fcabf6fe06536eeec43eec5", + "11e09447d40b22dc98070eec", + "da5ee1ec02eab13220fcb94f16efec848a8dd57c0f4d67955423f5d17fde5aa3", + "8f13e61d773a250810f75d46bf163a3f9205be5751f6049a", + "92a103b03764c1ad1f88500d22eeae5c0fe1044c872987c0b97affc5e8c3d783f8cc28a11dc91990ea22dd1bad74", + }, + { + "a1d960bda08efcf19e136dc1e8b05b6b381c820eda5f9a8047e1a2dd1803a1e4d11a7f", + "aa73d8d4aaa0cfd9d80a9ae8", + "08028833d617c28ba75b48f177cb5da87189189abb68dcb8974eca9230c25945", + "f7b6f34a910fd11588f567de8555932291f7df05f6e2b193", + "99cfc4cca193998bae153b744e6c94a82a2867780aa0f43acddb7c433fcb297311313ec2199f00d7ca7da0646b40113c60e935", + }, + { + "3b4ae39a745b6247ce5baf675ec36c5065b1bf76c8379eab4b769961d43a753896d068938017777e", + "128c017a985052f8cdbc6b28", + "4683d5caff613187a9b16af897253848e9c54fc0ec319de62452a86961d3cbb2", + "5612a13c2da003b91188921cbac3fa093eba99d8cbbb51ff", + "91a98b93b2174257175f7c882b45cc252e0db8667612bd270c1c12fe28b6bf209760bf8f370318f92ae3f88a5d4773b05714132cc28dddb8", + }, + { + "22ccf680d2995ef6563de281cff76882a036a59ad73f250e710b3040590d69bccde8a8411abe8b0d3cb728ca82", + "13a97d0a167a61aa21e531ec", + "9e140762eed274948b66de25e6e8f36ab65dc730b0cb096ef15aaba900a5588c", + "d0e9594cfd42ab72553bf34062a263f588bb8f1fc86a19f5", + "f194fc866dfba30e42c4508b7d90b3fa3f8983831ede713334563e36aa861f2f885b40be1dbe20ba2d10958a12823588d4bbbefb81a87d87315204f5e3", + }, + { + "a65f5d10c482b3381af296e631eb605eba6a11ccec6ceab021460d0bd35feb676ec6dbba5d4ad6c9f4d683ea541035bc80fa", + "f15ae71ffed50a8fcc4996b0", + "f535d60e8b75ac7e526041eed86eb4d65ae7e315eff15dba6c0133acc2a6a4bf", + "01ba61691ebb3c66d2f94c1b1c597ecd7b5ff7d2a30be405", + "d79e7c3893df5a5879c2f0a3f7ca619f08e4540f3ac7db35790b4211b9d47ae735adadf35fd47252a4763e3fd2b2cd8157f6ea7986108a53437962670a97d68ee281", + }, + { + "8c014655b97f6da76b0b168b565fd62de874c164fd7e227346a0ec22c908bed1e2a0b429620e6f3a68dd518f13a2c0250608a1cb08a7c3", + "10a7eff999029c5040c1b3bd", + "bf11af23e88c350a443493f6fa0eb34f234f4daa2676e26f0701bce5642d13f4", + "f14c97392afd2e32e2c625910ca029f9b6e81676c79cc42f", + "78d5226f372d5d60681dbfc749d12df74249f196b0cbf14fa65a3a59dc65ae458455ec39baa1df3397afe752bb06f6f13bf03c99abda7a95c1d0b73fd92d5f888a5f6f889a9aea", + }, + { + "66234d7a5b71eef134d60eccf7d5096ee879a33983d6f7a575e3a5e3a4022edccffe7865dde20b5b0a37252e31cb9a3650c63e35b057a1bc200a5b5b", + "ccc2406f997bcae737ddd0f5", + "d009eeb5b9b029577b14d200b7687b655eedb7d74add488f092681787999d66d", + "99319712626b400f9458dbb7a9abc9f5810f25b47fc90b39", + "543a2bbf52fd999027ae7c297353f3ce986f810bc2382583d0a81fda5939e4c87b6e8d262790cd614d6f753d8035b32adf43acc7f6d4c2c44289538928564b6587c2fcb99de1d8e34ffff323", + }, } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go new file mode 100644 index 0000000..a02fa57 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go @@ -0,0 +1,104 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package chacha20poly1305 + +import ( + "crypto/cipher" + "encoding/binary" + "errors" + + "golang.org/x/crypto/internal/chacha20" +) + +type xchacha20poly1305 struct { + key [8]uint32 +} + +// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. +// +// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, +// suitable to be generated randomly without risk of collisions. It should be +// preferred when nonce uniqueness cannot be trivially ensured, or whenever +// nonces are randomly generated. +func NewX(key []byte) (cipher.AEAD, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(xchacha20poly1305) + ret.key[0] = binary.LittleEndian.Uint32(key[0:4]) + ret.key[1] = binary.LittleEndian.Uint32(key[4:8]) + ret.key[2] = binary.LittleEndian.Uint32(key[8:12]) + ret.key[3] = binary.LittleEndian.Uint32(key[12:16]) + ret.key[4] = binary.LittleEndian.Uint32(key[16:20]) + ret.key[5] = binary.LittleEndian.Uint32(key[20:24]) + ret.key[6] = binary.LittleEndian.Uint32(key[24:28]) + ret.key[7] = binary.LittleEndian.Uint32(key[28:32]) + return ret, nil +} + +func (*xchacha20poly1305) NonceSize() int { + return NonceSizeX +} + +func (*xchacha20poly1305) Overhead() int { + return 16 +} + +func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSizeX { + panic("chacha20poly1305: bad nonce length passed to Seal") + } + + // XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no + // size limit. However, since we reuse the ChaCha20-Poly1305 implementation, + // the second half of the counter is not available. This is unlikely to be + // an issue because the cipher.AEAD API requires the entire message to be in + // memory, and the counter overflows at 256 GB. + if uint64(len(plaintext)) > (1<<38)-64 { + panic("chacha20poly1305: plaintext too large") + } + + hNonce := [4]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + binary.LittleEndian.Uint32(nonce[12:16]), + } + c := &chacha20poly1305{ + key: chacha20.HChaCha20(&x.key, &hNonce), + } + // The first 4 bytes of the final nonce are unused counter space. + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + + return c.seal(dst, cNonce[:], plaintext, additionalData) +} + +func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSizeX { + panic("chacha20poly1305: bad nonce length passed to Open") + } + if len(ciphertext) < 16 { + return nil, errOpen + } + if uint64(len(ciphertext)) > (1<<38)-48 { + panic("chacha20poly1305: ciphertext too large") + } + + hNonce := [4]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + binary.LittleEndian.Uint32(nonce[12:16]), + } + c := &chacha20poly1305{ + key: chacha20.HChaCha20(&x.key, &hNonce), + } + // The first 4 bytes of the final nonce are unused counter space. + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + + return c.open(dst, cNonce[:], ciphertext, additionalData) +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go index 88ec8b4..528b9bf 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1.go +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go @@ -23,6 +23,12 @@ func (b *Builder) AddASN1Int64(v int64) { b.addASN1Signed(asn1.INTEGER, v) } +// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the +// given tag. +func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { + b.addASN1Signed(tag, v) +} + // AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. func (b *Builder) AddASN1Enum(v int64) { b.addASN1Signed(asn1.ENUM, v) @@ -224,6 +230,9 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { // String +// ReadASN1Boolean decodes an ASN.1 INTEGER and converts it to a boolean +// representation into out and advances. It reports whether the read +// was successful. func (s *String) ReadASN1Boolean(out *bool) bool { var bytes String if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 { @@ -245,8 +254,8 @@ func (s *String) ReadASN1Boolean(out *bool) bool { var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem() // ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does -// not point to an integer or to a big.Int, it panics. It returns true on -// success and false on error. +// not point to an integer or to a big.Int, it panics. It reports whether the +// read was successful. func (s *String) ReadASN1Integer(out interface{}) bool { if reflect.TypeOf(out).Kind() != reflect.Ptr { panic("out is not a pointer") @@ -359,8 +368,16 @@ func asn1Unsigned(out *uint64, n []byte) bool { return true } -// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns -// true on success and false on error. +// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out +// and advances. It reports whether the read was successful and resulted in a +// value that can be represented in an int64. +func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { + var bytes String + return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) +} + +// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports +// whether the read was successful. func (s *String) ReadASN1Enum(out *int) bool { var bytes String var i int64 @@ -392,7 +409,7 @@ func (s *String) readBase128Int(out *int) bool { } // ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { var bytes String if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { @@ -431,7 +448,7 @@ func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) b } // ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { var bytes String if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { @@ -449,8 +466,8 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { return true } -// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It -// returns true on success and false on error. +// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. +// It reports whether the read was successful. func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { var bytes String if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { @@ -471,8 +488,8 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { } // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is -// an error if the BIT STRING is not a whole number of bytes. This function -// returns true on success and false on error. +// an error if the BIT STRING is not a whole number of bytes. It reports +// whether the read was successful. func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { var bytes String if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { @@ -489,14 +506,14 @@ func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { // ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool { return s.ReadASN1((*String)(out), tag) } // ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadASN1(out *String, tag asn1.Tag) bool { @@ -509,7 +526,7 @@ func (s *String) ReadASN1(out *String, tag asn1.Tag) bool { // ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool { @@ -521,8 +538,8 @@ func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool { } // ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including -// tag and length bytes) into out, sets outTag to its tag, and advances. It -// returns true on success and false on error. +// tag and length bytes) into out, sets outTag to its tag, and advances. +// It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool { @@ -531,14 +548,14 @@ func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool { // ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element // (including tag and length bytes) into out, sets outTag to is tag, and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool { return s.readASN1(out, outTag, false /* include header */) } -// PeekASN1Tag returns true if the next ASN.1 value on the string starts with +// PeekASN1Tag reports whether the next ASN.1 value on the string starts with // the given tag. func (s String) PeekASN1Tag(tag asn1.Tag) bool { if len(s) == 0 { @@ -547,7 +564,8 @@ func (s String) PeekASN1Tag(tag asn1.Tag) bool { return asn1.Tag(s[0]) == tag } -// SkipASN1 reads and discards an ASN.1 element with the given tag. +// SkipASN1 reads and discards an ASN.1 element with the given tag. It +// reports whether the operation was successful. func (s *String) SkipASN1(tag asn1.Tag) bool { var unused String return s.ReadASN1(&unused, tag) @@ -556,7 +574,7 @@ func (s *String) SkipASN1(tag asn1.Tag) bool { // ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1 // element (not including tag and length bytes) tagged with the given tag into // out. It stores whether an element with the tag was found in outPresent, -// unless outPresent is nil. It returns true on success and false on error. +// unless outPresent is nil. It reports whether the read was successful. func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool { present := s.PeekASN1Tag(tag) if outPresent != nil { @@ -569,7 +587,7 @@ func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) b } // SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or -// else leaves s unchanged. +// else leaves s unchanged. It reports whether the operation was successful. func (s *String) SkipOptionalASN1(tag asn1.Tag) bool { if !s.PeekASN1Tag(tag) { return true @@ -581,8 +599,8 @@ func (s *String) SkipOptionalASN1(tag asn1.Tag) bool { // ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER // explicitly tagged with tag into out and advances. If no element with a // matching tag is present, it writes defaultValue into out instead. If out -// does not point to an integer or to a big.Int, it panics. It returns true on -// success and false on error. +// does not point to an integer or to a big.Int, it panics. It reports +// whether the read was successful. func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool { if reflect.TypeOf(out).Kind() != reflect.Ptr { panic("out is not a pointer") @@ -619,8 +637,8 @@ func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultV // ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING // explicitly tagged with tag into out and advances. If no element with a -// matching tag is present, it writes defaultValue into out instead. It returns -// true on success and false on error. +// matching tag is present, it sets "out" to nil instead. It reports +// whether the read was successful. func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool { var present bool var child String @@ -644,6 +662,7 @@ func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag // ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or, // if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue. +// It reports whether the operation was successful. func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool { var present bool var child String diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go index ee6674a..9f6c952 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go @@ -149,6 +149,39 @@ func TestReadASN1IntegerSigned(t *testing.T) { } } }) + + // Repeat with the implicit-tagging functions + t.Run("WithTag", func(t *testing.T) { + for i, test := range testData64 { + tag := asn1.Tag((i * 3) % 32).ContextSpecific() + + testData := make([]byte, len(test.in)) + copy(testData, test.in) + + // Alter the tag of the test case. + testData[0] = uint8(tag) + + in := String(testData) + var out int64 + ok := in.ReadASN1Int64WithTag(&out, tag) + if !ok || out != test.out { + t.Errorf("#%d: in.ReadASN1Int64WithTag() = %v, want true; out = %d, want %d", i, ok, out, test.out) + } + + var b Builder + b.AddASN1Int64WithTag(test.out, tag) + result, err := b.Bytes() + + if err != nil { + t.Errorf("#%d: AddASN1Int64WithTag failed: %s", i, err) + continue + } + + if !bytes.Equal(result, testData) { + t.Errorf("#%d: AddASN1Int64WithTag: got %x, want %x", i, result, testData) + } + } + }) } func TestReadASN1IntegerUnsigned(t *testing.T) { diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go index 7636fb9..39bf98a 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/string.go +++ b/vendor/golang.org/x/crypto/cryptobyte/string.go @@ -37,8 +37,8 @@ func (s *String) Skip(n int) bool { return s.read(n) != nil } -// ReadUint8 decodes an 8-bit value into out and advances over it. It -// returns true on success and false on error. +// ReadUint8 decodes an 8-bit value into out and advances over it. +// It reports whether the read was successful. func (s *String) ReadUint8(out *uint8) bool { v := s.read(1) if v == nil { @@ -49,7 +49,7 @@ func (s *String) ReadUint8(out *uint8) bool { } // ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint16(out *uint16) bool { v := s.read(2) if v == nil { @@ -60,7 +60,7 @@ func (s *String) ReadUint16(out *uint16) bool { } // ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint24(out *uint32) bool { v := s.read(3) if v == nil { @@ -71,7 +71,7 @@ func (s *String) ReadUint24(out *uint32) bool { } // ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint32(out *uint32) bool { v := s.read(4) if v == nil { @@ -119,28 +119,27 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { } // ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value -// into out and advances over it. It returns true on success and false on -// error. +// into out and advances over it. It reports whether the read was successful. func (s *String) ReadUint8LengthPrefixed(out *String) bool { return s.readLengthPrefixed(1, out) } // ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit -// length-prefixed value into out and advances over it. It returns true on -// success and false on error. +// length-prefixed value into out and advances over it. It reports whether the +// read was successful. func (s *String) ReadUint16LengthPrefixed(out *String) bool { return s.readLengthPrefixed(2, out) } // ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit -// length-prefixed value into out and advances over it. It returns true on -// success and false on error. +// length-prefixed value into out and advances over it. It reports whether +// the read was successful. func (s *String) ReadUint24LengthPrefixed(out *String) bool { return s.readLengthPrefixed(3, out) } -// ReadBytes reads n bytes into out and advances over them. It returns true on -// success and false and error. +// ReadBytes reads n bytes into out and advances over them. It reports +// whether the read was successful. func (s *String) ReadBytes(out *[]byte, n int) bool { v := s.read(n) if v == nil { @@ -150,8 +149,8 @@ func (s *String) ReadBytes(out *[]byte, n int) bool { return true } -// CopyBytes copies len(out) bytes into out and advances over them. It returns -// true on success and false on error. +// CopyBytes copies len(out) bytes into out and advances over them. It reports +// whether the copy operation was successful func (s *String) CopyBytes(out []byte) bool { n := len(out) v := s.read(n) diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go index 4f26b49..d6f683b 100644 --- a/vendor/golang.org/x/crypto/ed25519/ed25519.go +++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go @@ -6,7 +6,10 @@ // https://ed25519.cr.yp.to/. // // These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. +// RFC 8032. However, unlike RFC 8032's formulation, this package's private key +// representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the RFC +// 8032 private key as the “seed”. package ed25519 // This code is a port of the public domain, “ref10” implementation of ed25519 @@ -31,6 +34,8 @@ const ( PrivateKeySize = 64 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 ) // PublicKey is the type of Ed25519 public keys. @@ -46,6 +51,15 @@ func (priv PrivateKey) Public() crypto.PublicKey { return PublicKey(publicKey) } +// Seed returns the private key seed corresponding to priv. It is provided for +// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds +// in this package. +func (priv PrivateKey) Seed() []byte { + seed := make([]byte, SeedSize) + copy(seed, priv[:32]) + return seed +} + // Sign signs the given message with priv. // Ed25519 performs two passes over messages to be signed and therefore cannot // handle pre-hashed messages. Thus opts.HashFunc() must return zero to @@ -61,19 +75,33 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp // GenerateKey generates a public/private key pair using entropy from rand. // If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { if rand == nil { rand = cryptorand.Reader } - privateKey = make([]byte, PrivateKeySize) - publicKey = make([]byte, PublicKeySize) - _, err = io.ReadFull(rand, privateKey[:32]) - if err != nil { + seed := make([]byte, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { return nil, nil, err } - digest := sha512.Sum512(privateKey[:32]) + privateKey := NewKeyFromSeed(seed) + publicKey := make([]byte, PublicKeySize) + copy(publicKey, privateKey[32:]) + + return publicKey, privateKey, nil +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + if l := len(seed); l != SeedSize { + panic("ed25519: bad seed length: " + strconv.Itoa(l)) + } + + digest := sha512.Sum512(seed) digest[0] &= 248 digest[31] &= 127 digest[31] |= 64 @@ -85,10 +113,11 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er var publicKeyBytes [32]byte A.ToBytes(&publicKeyBytes) + privateKey := make([]byte, PrivateKeySize) + copy(privateKey, seed) copy(privateKey[32:], publicKeyBytes[:]) - copy(publicKey, publicKeyBytes[:]) - return publicKey, privateKey, nil + return privateKey } // Sign signs the message with privateKey and returns a signature. It will @@ -171,9 +200,16 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { edwards25519.ScReduce(&hReduced, &digest) var R edwards25519.ProjectiveGroupElement - var b [32]byte - copy(b[:], sig[32:]) - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) + var s [32]byte + copy(s[:], sig[32:]) + + // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in + // the range [0, order) in order to prevent signature malleability. + if !edwards25519.ScMinimal(&s) { + return false + } + + edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) var checkR [32]byte R.ToBytes(&checkR) diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go index e272f8a..8094603 100644 --- a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go +++ b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go @@ -139,6 +139,19 @@ func TestGolden(t *testing.T) { if !Verify(pubKey, msg, sig2) { t.Errorf("signature failed to verify on line %d", lineNo) } + + priv2 := NewKeyFromSeed(priv[:32]) + if !bytes.Equal(priv[:], priv2) { + t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) + } + + if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { + t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) + } + + if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { + t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) + } } if err := scanner.Err(); err != nil { @@ -146,6 +159,30 @@ func TestGolden(t *testing.T) { } } +func TestMalleability(t *testing.T) { + // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test + // that s be in [0, order). This prevents someone from adding a multiple of + // order to s and obtaining a second valid signature for the same message. + msg := []byte{0x54, 0x65, 0x73, 0x74} + sig := []byte{ + 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, + 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, + 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, + 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, + 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, + 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, + } + publicKey := []byte{ + 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, + 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, + 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, + } + + if Verify(publicKey, msg, sig) { + t.Fatal("non-canonical signature accepted") + } +} + func BenchmarkKeyGeneration(b *testing.B) { var zero zeroReader for i := 0; i < b.N; i++ { diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go index 5f8b994..fd03c25 100644 --- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go +++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -4,6 +4,8 @@ package edwards25519 +import "encoding/binary" + // This code is a port of the public domain, “ref10” implementation of ed25519 // from SUPERCOP. @@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) { out[30] = byte(s11 >> 9) out[31] = byte(s11 >> 17) } + +// order is the order of Curve25519 in little-endian form. +var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} + +// ScMinimal returns true if the given scalar is less than the order of the +// curve. +func ScMinimal(scalar *[32]byte) bool { + for i := 3; ; i-- { + v := binary.LittleEndian.Uint64(scalar[i*8:]) + if v > order[i] { + return false + } else if v < order[i] { + break + } else if i == 0 { + return false + } + } + + return true +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go index 0f8efdb..6570847 100644 --- a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go @@ -2,197 +2,263 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3. +// Package ChaCha20 implements the core ChaCha20 function as specified +// in https://tools.ietf.org/html/rfc7539#section-2.3. package chacha20 -import "encoding/binary" +import ( + "crypto/cipher" + "encoding/binary" -const rounds = 20 + "golang.org/x/crypto/internal/subtle" +) -// core applies the ChaCha20 core function to 16-byte input in, 32-byte key k, -// and 16-byte constant c, and puts the result into 64-byte array out. -func core(out *[64]byte, in *[16]byte, k *[32]byte) { - j0 := uint32(0x61707865) - j1 := uint32(0x3320646e) - j2 := uint32(0x79622d32) - j3 := uint32(0x6b206574) - j4 := binary.LittleEndian.Uint32(k[0:4]) - j5 := binary.LittleEndian.Uint32(k[4:8]) - j6 := binary.LittleEndian.Uint32(k[8:12]) - j7 := binary.LittleEndian.Uint32(k[12:16]) - j8 := binary.LittleEndian.Uint32(k[16:20]) - j9 := binary.LittleEndian.Uint32(k[20:24]) - j10 := binary.LittleEndian.Uint32(k[24:28]) - j11 := binary.LittleEndian.Uint32(k[28:32]) - j12 := binary.LittleEndian.Uint32(in[0:4]) - j13 := binary.LittleEndian.Uint32(in[4:8]) - j14 := binary.LittleEndian.Uint32(in[8:12]) - j15 := binary.LittleEndian.Uint32(in[12:16]) +// assert that *Cipher implements cipher.Stream +var _ cipher.Stream = (*Cipher)(nil) - x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7 - x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15 +// Cipher is a stateful instance of ChaCha20 using a particular key +// and nonce. A *Cipher implements the cipher.Stream interface. +type Cipher struct { + key [8]uint32 + counter uint32 // incremented after each block + nonce [3]uint32 + buf [bufSize]byte // buffer for unused keystream bytes + len int // number of unused keystream bytes at end of buf +} - for i := 0; i < rounds; i += 2 { - x0 += x4 - x12 ^= x0 - x12 = (x12 << 16) | (x12 >> (16)) - x8 += x12 - x4 ^= x8 - x4 = (x4 << 12) | (x4 >> (20)) - x0 += x4 - x12 ^= x0 - x12 = (x12 << 8) | (x12 >> (24)) - x8 += x12 - x4 ^= x8 - x4 = (x4 << 7) | (x4 >> (25)) - x1 += x5 - x13 ^= x1 - x13 = (x13 << 16) | (x13 >> 16) - x9 += x13 - x5 ^= x9 - x5 = (x5 << 12) | (x5 >> 20) - x1 += x5 - x13 ^= x1 - x13 = (x13 << 8) | (x13 >> 24) - x9 += x13 - x5 ^= x9 - x5 = (x5 << 7) | (x5 >> 25) - x2 += x6 - x14 ^= x2 - x14 = (x14 << 16) | (x14 >> 16) - x10 += x14 - x6 ^= x10 - x6 = (x6 << 12) | (x6 >> 20) - x2 += x6 - x14 ^= x2 - x14 = (x14 << 8) | (x14 >> 24) - x10 += x14 - x6 ^= x10 - x6 = (x6 << 7) | (x6 >> 25) - x3 += x7 - x15 ^= x3 - x15 = (x15 << 16) | (x15 >> 16) - x11 += x15 - x7 ^= x11 - x7 = (x7 << 12) | (x7 >> 20) - x3 += x7 - x15 ^= x3 - x15 = (x15 << 8) | (x15 >> 24) - x11 += x15 - x7 ^= x11 - x7 = (x7 << 7) | (x7 >> 25) - x0 += x5 - x15 ^= x0 - x15 = (x15 << 16) | (x15 >> 16) - x10 += x15 - x5 ^= x10 - x5 = (x5 << 12) | (x5 >> 20) - x0 += x5 - x15 ^= x0 - x15 = (x15 << 8) | (x15 >> 24) - x10 += x15 - x5 ^= x10 - x5 = (x5 << 7) | (x5 >> 25) - x1 += x6 - x12 ^= x1 - x12 = (x12 << 16) | (x12 >> 16) - x11 += x12 - x6 ^= x11 - x6 = (x6 << 12) | (x6 >> 20) - x1 += x6 - x12 ^= x1 - x12 = (x12 << 8) | (x12 >> 24) - x11 += x12 - x6 ^= x11 - x6 = (x6 << 7) | (x6 >> 25) - x2 += x7 - x13 ^= x2 - x13 = (x13 << 16) | (x13 >> 16) - x8 += x13 - x7 ^= x8 - x7 = (x7 << 12) | (x7 >> 20) - x2 += x7 - x13 ^= x2 - x13 = (x13 << 8) | (x13 >> 24) - x8 += x13 - x7 ^= x8 - x7 = (x7 << 7) | (x7 >> 25) - x3 += x4 - x14 ^= x3 - x14 = (x14 << 16) | (x14 >> 16) - x9 += x14 - x4 ^= x9 - x4 = (x4 << 12) | (x4 >> 20) - x3 += x4 - x14 ^= x3 - x14 = (x14 << 8) | (x14 >> 24) - x9 += x14 - x4 ^= x9 - x4 = (x4 << 7) | (x4 >> 25) +// New creates a new ChaCha20 stream cipher with the given key and nonce. +// The initial counter value is set to 0. +func New(key [8]uint32, nonce [3]uint32) *Cipher { + return &Cipher{key: key, nonce: nonce} +} + +// ChaCha20 constants spelling "expand 32-byte k" +const ( + j0 uint32 = 0x61707865 + j1 uint32 = 0x3320646e + j2 uint32 = 0x79622d32 + j3 uint32 = 0x6b206574 +) + +func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { + a += b + d ^= a + d = (d << 16) | (d >> 16) + c += d + b ^= c + b = (b << 12) | (b >> 20) + a += b + d ^= a + d = (d << 8) | (d >> 24) + c += d + b ^= c + b = (b << 7) | (b >> 25) + return a, b, c, d +} + +// XORKeyStream XORs each byte in the given slice with a byte from the +// cipher's key stream. Dst and src must overlap entirely or not at all. +// +// If len(dst) < len(src), XORKeyStream will panic. It is acceptable +// to pass a dst bigger than src, and in that case, XORKeyStream will +// only update dst[:len(src)] and will not touch the rest of dst. +// +// Multiple calls to XORKeyStream behave as if the concatenation of +// the src buffers was passed in a single run. That is, Cipher +// maintains state and does not reset at each XORKeyStream call. +func (s *Cipher) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("chacha20: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("chacha20: invalid buffer overlap") } - x0 += j0 - x1 += j1 - x2 += j2 - x3 += j3 - x4 += j4 - x5 += j5 - x6 += j6 - x7 += j7 - x8 += j8 - x9 += j9 - x10 += j10 - x11 += j11 - x12 += j12 - x13 += j13 - x14 += j14 - x15 += j15 + // xor src with buffered keystream first + if s.len != 0 { + buf := s.buf[len(s.buf)-s.len:] + if len(src) < len(buf) { + buf = buf[:len(src)] + } + td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint + for i, b := range buf { + td[i] = ts[i] ^ b + } + s.len -= len(buf) + if s.len != 0 { + return + } + s.buf = [len(s.buf)]byte{} // zero the empty buffer + src = src[len(buf):] + dst = dst[len(buf):] + } - binary.LittleEndian.PutUint32(out[0:4], x0) - binary.LittleEndian.PutUint32(out[4:8], x1) - binary.LittleEndian.PutUint32(out[8:12], x2) - binary.LittleEndian.PutUint32(out[12:16], x3) - binary.LittleEndian.PutUint32(out[16:20], x4) - binary.LittleEndian.PutUint32(out[20:24], x5) - binary.LittleEndian.PutUint32(out[24:28], x6) - binary.LittleEndian.PutUint32(out[28:32], x7) - binary.LittleEndian.PutUint32(out[32:36], x8) - binary.LittleEndian.PutUint32(out[36:40], x9) - binary.LittleEndian.PutUint32(out[40:44], x10) - binary.LittleEndian.PutUint32(out[44:48], x11) - binary.LittleEndian.PutUint32(out[48:52], x12) - binary.LittleEndian.PutUint32(out[52:56], x13) - binary.LittleEndian.PutUint32(out[56:60], x14) - binary.LittleEndian.PutUint32(out[60:64], x15) + if len(src) == 0 { + return + } + if haveAsm { + if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 { + panic("chacha20: counter overflow") + } + s.xorKeyStreamAsm(dst, src) + return + } + + // set up a 64-byte buffer to pad out the final block if needed + // (hoisted out of the main loop to avoid spills) + rem := len(src) % 64 // length of final block + fin := len(src) - rem // index of final block + if rem > 0 { + copy(s.buf[len(s.buf)-64:], src[fin:]) + } + + // pre-calculate most of the first round + s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0]) + s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1]) + s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2]) + + n := len(src) + src, dst = src[:n:n], dst[:n:n] // BCE hint + for i := 0; i < n; i += 64 { + // calculate the remainder of the first round + s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter) + + // execute the second round + x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15) + x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12) + x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13) + x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14) + + // execute the remaining 18 rounds + for i := 0; i < 9; i++ { + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + + x4 += s.key[0] + x5 += s.key[1] + x6 += s.key[2] + x7 += s.key[3] + x8 += s.key[4] + x9 += s.key[5] + x10 += s.key[6] + x11 += s.key[7] + + x12 += s.counter + x13 += s.nonce[0] + x14 += s.nonce[1] + x15 += s.nonce[2] + + // increment the counter + s.counter += 1 + if s.counter == 0 { + panic("chacha20: counter overflow") + } + + // pad to 64 bytes if needed + in, out := src[i:], dst[i:] + if i == fin { + // src[fin:] has already been copied into s.buf before + // the main loop + in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:] + } + in, out = in[:64], out[:64] // BCE hint + + // XOR the key stream with the source and write out the result + xor(out[0:], in[0:], x0) + xor(out[4:], in[4:], x1) + xor(out[8:], in[8:], x2) + xor(out[12:], in[12:], x3) + xor(out[16:], in[16:], x4) + xor(out[20:], in[20:], x5) + xor(out[24:], in[24:], x6) + xor(out[28:], in[28:], x7) + xor(out[32:], in[32:], x8) + xor(out[36:], in[36:], x9) + xor(out[40:], in[40:], x10) + xor(out[44:], in[44:], x11) + xor(out[48:], in[48:], x12) + xor(out[52:], in[52:], x13) + xor(out[56:], in[56:], x14) + xor(out[60:], in[60:], x15) + } + // copy any trailing bytes out of the buffer and into dst + if rem != 0 { + s.len = 64 - rem + copy(dst[fin:], s.buf[len(s.buf)-64:]) + } +} + +// Advance discards bytes in the key stream until the next 64 byte block +// boundary is reached and updates the counter accordingly. If the key +// stream is already at a block boundary no bytes will be discarded and +// the counter will be unchanged. +func (s *Cipher) Advance() { + s.len -= s.len % 64 + if s.len == 0 { + s.buf = [len(s.buf)]byte{} + } } // XORKeyStream crypts bytes from in to out using the given key and counters. // In and out must overlap entirely or not at all. Counter contains the raw // ChaCha20 counter bytes (i.e. block counter followed by nonce). func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { - var block [64]byte - var counterCopy [16]byte - copy(counterCopy[:], counter[:]) - - for len(in) >= 64 { - core(&block, &counterCopy, key) - for i, x := range block { - out[i] = in[i] ^ x - } - u := uint32(1) - for i := 0; i < 4; i++ { - u += uint32(counterCopy[i]) - counterCopy[i] = byte(u) - u >>= 8 - } - in = in[64:] - out = out[64:] - } - - if len(in) > 0 { - core(&block, &counterCopy, key) - for i, v := range in { - out[i] = v ^ block[i] - } + s := Cipher{ + key: [8]uint32{ + binary.LittleEndian.Uint32(key[0:4]), + binary.LittleEndian.Uint32(key[4:8]), + binary.LittleEndian.Uint32(key[8:12]), + binary.LittleEndian.Uint32(key[12:16]), + binary.LittleEndian.Uint32(key[16:20]), + binary.LittleEndian.Uint32(key[20:24]), + binary.LittleEndian.Uint32(key[24:28]), + binary.LittleEndian.Uint32(key[28:32]), + }, + nonce: [3]uint32{ + binary.LittleEndian.Uint32(counter[4:8]), + binary.LittleEndian.Uint32(counter[8:12]), + binary.LittleEndian.Uint32(counter[12:16]), + }, + counter: binary.LittleEndian.Uint32(counter[0:4]), } + s.XORKeyStream(out, in) +} + +// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a +// nonce. It should only be used as part of the XChaCha20 construction. +func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 { + x0, x1, x2, x3 := j0, j1, j2, j3 + x4, x5, x6, x7 := key[0], key[1], key[2], key[3] + x8, x9, x10, x11 := key[4], key[5], key[6], key[7] + x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3] + + for i := 0; i < 10; i++ { + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + var out [8]uint32 + out[0], out[1], out[2], out[3] = x0, x1, x2, x3 + out[4], out[5], out[6], out[7] = x12, x13, x14, x15 + return out } diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go new file mode 100644 index 0000000..91520d1 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go @@ -0,0 +1,16 @@ +// Copyright 2018 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. + +// +build !s390x gccgo appengine + +package chacha20 + +const ( + bufSize = 64 + haveAsm = false +) + +func (*Cipher) xorKeyStreamAsm(dst, src []byte) { + panic("not implemented") +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go new file mode 100644 index 0000000..0c1c671 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go @@ -0,0 +1,30 @@ +// Copyright 2018 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. + +// +build s390x,!gccgo,!appengine + +package chacha20 + +var haveAsm = hasVectorFacility() + +const bufSize = 256 + +// hasVectorFacility reports whether the machine supports the vector +// facility (vx). +// Implementation in asm_s390x.s. +func hasVectorFacility() bool + +// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only +// be called when the vector facility is available. +// Implementation in asm_s390x.s. +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int) + +func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len) +} + +// EXRL targets, DO NOT CALL! +func mvcSrcToBuf() +func mvcBufToDst() diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s new file mode 100644 index 0000000..98427c5 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s @@ -0,0 +1,283 @@ +// Copyright 2018 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. + +// +build s390x,!gccgo,!appengine + +#include "go_asm.h" +#include "textflag.h" + +// This is an implementation of the ChaCha20 encryption algorithm as +// specified in RFC 7539. It uses vector instructions to compute +// 4 keystream blocks in parallel (256 bytes) which are then XORed +// with the bytes in the input slice. + +GLOBL ·constants<>(SB), RODATA|NOPTR, $32 +// BSWAP: swap bytes in each 4-byte element +DATA ·constants<>+0x00(SB)/4, $0x03020100 +DATA ·constants<>+0x04(SB)/4, $0x07060504 +DATA ·constants<>+0x08(SB)/4, $0x0b0a0908 +DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c +// J0: [j0, j1, j2, j3] +DATA ·constants<>+0x10(SB)/4, $0x61707865 +DATA ·constants<>+0x14(SB)/4, $0x3320646e +DATA ·constants<>+0x18(SB)/4, $0x79622d32 +DATA ·constants<>+0x1c(SB)/4, $0x6b206574 + +// EXRL targets: +TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0 + MVC $1, (R1), (R8) + RET + +TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0 + MVC $1, (R8), (R9) + RET + +#define BSWAP V5 +#define J0 V6 +#define KEY0 V7 +#define KEY1 V8 +#define NONCE V9 +#define CTR V10 +#define M0 V11 +#define M1 V12 +#define M2 V13 +#define M3 V14 +#define INC V15 +#define X0 V16 +#define X1 V17 +#define X2 V18 +#define X3 V19 +#define X4 V20 +#define X5 V21 +#define X6 V22 +#define X7 V23 +#define X8 V24 +#define X9 V25 +#define X10 V26 +#define X11 V27 +#define X12 V28 +#define X13 V29 +#define X14 V30 +#define X15 V31 + +#define NUM_ROUNDS 20 + +#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $16, a2, a2 \ + VERLLF $16, b2, b2 \ + VERLLF $16, c2, c2 \ + VERLLF $16, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $12, a1, a1 \ + VERLLF $12, b1, b1 \ + VERLLF $12, c1, c1 \ + VERLLF $12, d1, d1 \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $8, a2, a2 \ + VERLLF $8, b2, b2 \ + VERLLF $8, c2, c2 \ + VERLLF $8, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $7, a1, a1 \ + VERLLF $7, b1, b1 \ + VERLLF $7, c1, c1 \ + VERLLF $7, d1, d1 + +#define PERMUTE(mask, v0, v1, v2, v3) \ + VPERM v0, v0, mask, v0 \ + VPERM v1, v1, mask, v1 \ + VPERM v2, v2, mask, v2 \ + VPERM v3, v3, mask, v3 + +#define ADDV(x, v0, v1, v2, v3) \ + VAF x, v0, v0 \ + VAF x, v1, v1 \ + VAF x, v2, v2 \ + VAF x, v3, v3 + +#define XORV(off, dst, src, v0, v1, v2, v3) \ + VLM off(src), M0, M3 \ + PERMUTE(BSWAP, v0, v1, v2, v3) \ + VX v0, M0, M0 \ + VX v1, M1, M1 \ + VX v2, M2, M2 \ + VX v3, M3, M3 \ + VSTM M0, M3, off(dst) + +#define SHUFFLE(a, b, c, d, t, u, v, w) \ + VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} + VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} + VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} + VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} + VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} + VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} + VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} + VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD $·constants<>(SB), R1 + MOVD dst+0(FP), R2 // R2=&dst[0] + LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) + MOVD key+48(FP), R5 // R5=key + MOVD nonce+56(FP), R6 // R6=nonce + MOVD counter+64(FP), R7 // R7=counter + MOVD buf+72(FP), R8 // R8=buf + MOVD len+80(FP), R9 // R9=len + + // load BSWAP and J0 + VLM (R1), BSWAP, J0 + + // set up tail buffer + ADD $-1, R4, R12 + MOVBZ R12, R12 + CMPUBEQ R12, $255, aligned + MOVD R4, R1 + AND $~255, R1 + MOVD $(R3)(R1*1), R1 + EXRL $·mvcSrcToBuf(SB), R12 + MOVD $255, R0 + SUB R12, R0 + MOVD R0, (R9) // update len + +aligned: + // setup + MOVD $95, R0 + VLM (R5), KEY0, KEY1 + VLL R0, (R6), NONCE + VZERO M0 + VLEIB $7, $32, M0 + VSRLB M0, NONCE, NONCE + + // initialize counter values + VLREPF (R7), CTR + VZERO INC + VLEIF $1, $1, INC + VLEIF $2, $2, INC + VLEIF $3, $3, INC + VAF INC, CTR, CTR + VREPIF $4, INC + +chacha: + VREPF $0, J0, X0 + VREPF $1, J0, X1 + VREPF $2, J0, X2 + VREPF $3, J0, X3 + VREPF $0, KEY0, X4 + VREPF $1, KEY0, X5 + VREPF $2, KEY0, X6 + VREPF $3, KEY0, X7 + VREPF $0, KEY1, X8 + VREPF $1, KEY1, X9 + VREPF $2, KEY1, X10 + VREPF $3, KEY1, X11 + VLR CTR, X12 + VREPF $1, NONCE, X13 + VREPF $2, NONCE, X14 + VREPF $3, NONCE, X15 + + MOVD $(NUM_ROUNDS/2), R1 + +loop: + ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) + ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) + + ADD $-1, R1 + BNE loop + + // decrement length + ADD $-256, R4 + BLT tail + +continue: + // rearrange vectors + SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) + ADDV(J0, X0, X1, X2, X3) + SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) + ADDV(KEY0, X4, X5, X6, X7) + SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) + ADDV(KEY1, X8, X9, X10, X11) + VAF CTR, X12, X12 + SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) + ADDV(NONCE, X12, X13, X14, X15) + + // increment counters + VAF INC, CTR, CTR + + // xor keystream with plaintext + XORV(0*64, R2, R3, X0, X4, X8, X12) + XORV(1*64, R2, R3, X1, X5, X9, X13) + XORV(2*64, R2, R3, X2, X6, X10, X14) + XORV(3*64, R2, R3, X3, X7, X11, X15) + + // increment pointers + MOVD $256(R2), R2 + MOVD $256(R3), R3 + + CMPBNE R4, $0, chacha + CMPUBEQ R12, $255, return + EXRL $·mvcBufToDst(SB), R12 // len was updated during setup + +return: + VSTEF $0, CTR, (R7) + RET + +tail: + MOVD R2, R9 + MOVD R8, R2 + MOVD R8, R3 + MOVD $0, R4 + JMP continue + +// func hasVectorFacility() bool +TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x40, R1 + BEQ novector + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novector + MOVB $1, ret+0(FP) // have vx + RET + +novector: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go index b80d34c..9a7a099 100644 --- a/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go @@ -5,7 +5,10 @@ package chacha20 import ( + "encoding/binary" "encoding/hex" + "fmt" + "math/rand" "testing" ) @@ -31,3 +34,192 @@ func TestCore(t *testing.T) { t.Errorf("wanted %x but got %x", expected, result) } } + +// Run the test cases with the input and output in different buffers. +func TestNoOverlap(t *testing.T) { + for _, c := range testVectors { + s := New(c.key, c.nonce) + input, err := hex.DecodeString(c.input) + if err != nil { + t.Fatalf("cannot decode input %#v: %v", c.input, err) + } + output := make([]byte, c.length) + s.XORKeyStream(output, input) + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) + } + } +} + +// Run the test cases with the input and output overlapping entirely. +func TestOverlap(t *testing.T) { + for _, c := range testVectors { + s := New(c.key, c.nonce) + data, err := hex.DecodeString(c.input) + if err != nil { + t.Fatalf("cannot decode input %#v: %v", c.input, err) + } + s.XORKeyStream(data, data) + got := hex.EncodeToString(data) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) + } + } +} + +// Run the test cases with various source and destination offsets. +func TestUnaligned(t *testing.T) { + const max = 8 // max offset (+1) to test + for _, c := range testVectors { + input := make([]byte, c.length+max) + output := make([]byte, c.length+max) + for i := 0; i < max; i++ { // input offsets + for j := 0; j < max; j++ { // output offsets + s := New(c.key, c.nonce) + + input := input[i : i+c.length] + output := output[j : j+c.length] + + data, err := hex.DecodeString(c.input) + if err != nil { + t.Fatalf("cannot decode input %#v: %v", c.input, err) + } + copy(input, data) + s.XORKeyStream(output, input) + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) + } + } + } + } +} + +// Run the test cases by calling XORKeyStream multiple times. +func TestStep(t *testing.T) { + // wide range of step sizes to try and hit edge cases + steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} + rnd := rand.New(rand.NewSource(123)) + for _, c := range testVectors { + s := New(c.key, c.nonce) + input, err := hex.DecodeString(c.input) + if err != nil { + t.Fatalf("cannot decode input %#v: %v", c.input, err) + } + output := make([]byte, c.length) + + // step through the buffers + i, step := 0, steps[rnd.Intn(len(steps))] + for i+step < c.length { + s.XORKeyStream(output[i:i+step], input[i:i+step]) + if i+step < c.length && output[i+step] != 0 { + t.Errorf("length=%v, i=%v, step=%v: output overwritten", c.length, i, step) + } + i += step + step = steps[rnd.Intn(len(steps))] + } + // finish the encryption + s.XORKeyStream(output[i:], input[i:]) + + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) + } + } +} + +// Test that Advance() discards bytes until a block boundary is hit. +func TestAdvance(t *testing.T) { + for _, c := range testVectors { + for i := 0; i < 63; i++ { + s := New(c.key, c.nonce) + z := New(c.key, c.nonce) + input, err := hex.DecodeString(c.input) + if err != nil { + t.Fatalf("cannot decode input %#v: %v", c.input, err) + } + zeros, discard := make([]byte, 64), make([]byte, 64) + so, zo := make([]byte, c.length), make([]byte, c.length) + for j := 0; j < c.length; j += 64 { + lim := j + i + if lim > c.length { + lim = c.length + } + s.XORKeyStream(so[j:lim], input[j:lim]) + // calling s.Advance() multiple times should have no effect + for k := 0; k < i%3+1; k++ { + s.Advance() + } + z.XORKeyStream(zo[j:lim], input[j:lim]) + if lim < c.length { + end := 64 - i + if c.length-lim < end { + end = c.length - lim + } + z.XORKeyStream(discard[:], zeros[:end]) + } + } + + got := hex.EncodeToString(so) + want := hex.EncodeToString(zo) + if got != want { + t.Errorf("length=%v: got %#v, want %#v", c.length, got, want) + } + } + } +} + +func BenchmarkChaCha20(b *testing.B) { + sizes := []int{32, 63, 64, 256, 1024, 1350, 65536} + for _, size := range sizes { + s := size + b.Run(fmt.Sprint(s), func(b *testing.B) { + k := [32]byte{} + c := [16]byte{} + src := make([]byte, s) + dst := make([]byte, s) + b.SetBytes(int64(s)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + XORKeyStream(dst, src, &c, &k) + } + }) + } +} + +func TestHChaCha20(t *testing.T) { + // See draft-paragon-paseto-rfc-00 §7.2.1. + key := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} + nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} + expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, + 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, + 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, + 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, + } + result := HChaCha20(&[8]uint32{ + binary.LittleEndian.Uint32(key[0:4]), + binary.LittleEndian.Uint32(key[4:8]), + binary.LittleEndian.Uint32(key[8:12]), + binary.LittleEndian.Uint32(key[12:16]), + binary.LittleEndian.Uint32(key[16:20]), + binary.LittleEndian.Uint32(key[20:24]), + binary.LittleEndian.Uint32(key[24:28]), + binary.LittleEndian.Uint32(key[28:32]), + }, &[4]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + binary.LittleEndian.Uint32(nonce[12:16]), + }) + for i := 0; i < 8; i++ { + want := binary.LittleEndian.Uint32(expected[i*4 : (i+1)*4]) + if got := result[i]; got != want { + t.Errorf("word %d incorrect: want 0x%x, got 0x%x", i, want, got) + } + } +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go b/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go new file mode 100644 index 0000000..b441fbd --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go @@ -0,0 +1,578 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package chacha20 + +// Test vectors for ChaCha20 implementations. + +type testCase struct { + length int + nonce [3]uint32 + key [8]uint32 + input string + output string +} + +var testVectors = [...]testCase{ + { + length: 0, + nonce: [3]uint32{0x94d13317, 0x6b6a2b3, 0x3ffe0036}, + key: [8]uint32{0x9da8a3b6, 0x3abf4ae6, 0xa2f19cae, 0x1068c707, 0x72e4801e, 0xce165d92, 0x61e7028f, 0x82ac3d57}, + input: "", + output: "", + }, + { + length: 5, + nonce: [3]uint32{0x469fadd, 0xee3fcc1e, 0x45cf77b0}, + key: [8]uint32{0x3477e02b, 0x45bf809f, 0x27f4a1fa, 0xdb901de8, 0xd8a190dc, 0x1d2c21d4, 0x87bdf2ac, 0xdfbf0000}, + input: "23dbad0780", + output: "415a3e498d", + }, + { + length: 9, + nonce: [3]uint32{0x512a6b49, 0x8df9af6d, 0x5336a2a5}, + key: [8]uint32{0xe9124c25, 0x4fd1a373, 0x7945f7bb, 0xeed5f064, 0x29c4185d, 0x3c9acf13, 0x4c94a367, 0x7c2c2c53}, + input: "f518831fab69c054a6", + output: "cfe40f63f81391484b", + }, + { + length: 12, + nonce: [3]uint32{0xca697a9e, 0x6b2f6717, 0xb7859220}, + key: [8]uint32{0xfc825020, 0x5ca4410b, 0x7d5285d0, 0x160a1c9d, 0x15470b41, 0x3634742a, 0xe64aa7fa, 0xca0be67a}, + input: "805fad1d62951537aeed9859", + output: "47bd303f93c3ce04bce44710", + }, + { + length: 14, + nonce: [3]uint32{0xcded3db3, 0x35770a7f, 0x6aede9b}, + key: [8]uint32{0x44632def, 0xa5e420a7, 0xfc12a8f, 0x63b79a15, 0x337de314, 0xb82fbf16, 0x3104bc57, 0x677c9227}, + input: "f4e8a7577affb841cf48392cf5df", + output: "f445c0fb7e3d5bfdab47090ddee6", + }, + { + length: 15, + nonce: [3]uint32{0x348a50b1, 0x4acc9280, 0x8d6014ce}, + key: [8]uint32{0x34bd31a8, 0x2808f47e, 0x9d8b19f9, 0x4df59683, 0x31584348, 0x34a74a45, 0xde174a2, 0x29d4c7dc}, + input: "1179b71ec4dc34bd812f742b5a0b27", + output: "cc7f80f333c647d6e592e4f7ecc834", + }, + { + length: 20, + nonce: [3]uint32{0xc8754703, 0x9188c521, 0xac8ce8a6}, + key: [8]uint32{0xe93c79ed, 0xce89162b, 0x116a8366, 0xecdc657f, 0x5bc81d98, 0xff5d2f52, 0x171f3ebb, 0x50773f2f}, + input: "7bd94943d55392d0311c413ac755ce0347872ba3", + output: "c43665de15136af232675d9d5dbbeca77f3c542a", + }, + { + length: 21, + nonce: [3]uint32{0x9a8655cb, 0x6e9d6ea5, 0x5dad705e}, + key: [8]uint32{0x3542d5b3, 0x1f7bfd8f, 0x1038abf8, 0x7214e8ec, 0xedd05693, 0x60e663bd, 0xe8e5d506, 0xeea923a2}, + input: "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f", + output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86", + }, + { + length: 25, + nonce: [3]uint32{0x3f202ca4, 0x63fc86, 0x7260a10e}, + key: [8]uint32{0xe28ab1d6, 0xe83b3d47, 0x671271ca, 0xb977bcff, 0xa2f64476, 0x311d79b4, 0x180d91d0, 0xec1a6e0c}, + input: "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a", + output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b", + }, + { + length: 31, + nonce: [3]uint32{0xcf8671ea, 0x8d72df2f, 0x8b5a538a}, + key: [8]uint32{0xe46ca2bb, 0xd06ab5ef, 0xb0e2966b, 0x54dd0c2d, 0x8815d89a, 0x426c30a9, 0x15b0f1e, 0x254bae75}, + input: "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf", + output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc", + }, + { + length: 34, + nonce: [3]uint32{0xd1be983a, 0xf5aa389, 0xfa26c7e1}, + key: [8]uint32{0x795c6da7, 0x8cb1aadc, 0xa042359a, 0x95ea2e27, 0x128253c4, 0xaabc592f, 0x391e810, 0xf641d971}, + input: "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17", + output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e", + }, + { + length: 34, + nonce: [3]uint32{0x98f5f4b8, 0x3f181d73, 0x5bf4572e}, + key: [8]uint32{0xa86f8cf7, 0x8db41a2b, 0xe0e03156, 0x3dad8a59, 0xb3e4d1ba, 0x75f6fb38, 0xdb94709d, 0xc3db34f3}, + input: "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3", + output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb", + }, + { + length: 40, + nonce: [3]uint32{0x7289ae18, 0x7ebe7e50, 0x7d819176}, + key: [8]uint32{0x336c07a0, 0x4a2ea22b, 0xa8872f46, 0xa47b5e28, 0xbe645e3f, 0x371c6591, 0xd2dc237a, 0x92c59580}, + input: "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3", + output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6", + }, + { + length: 47, + nonce: [3]uint32{0xfd3181de, 0x8b193e26, 0xbebc799}, + key: [8]uint32{0x781a4c2e, 0x27ab55e2, 0x814aaf43, 0xa0bab01, 0x9de62ce0, 0x472b03d2, 0xdfee18e8, 0x8b855b93}, + input: "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e", + output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1", + }, + { + length: 51, + nonce: [3]uint32{0x27b02ff6, 0xa510613e, 0x218b22d8}, + key: [8]uint32{0x62fc7732, 0xcef06cf4, 0xa4f45ed5, 0x2f96654f, 0x9f2b956e, 0x42b572f4, 0x5bb59c86, 0x35e4784f}, + input: "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77", + output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c", + }, + { + length: 52, + nonce: [3]uint32{0x9db97a63, 0xff50248, 0xf2b6df56}, + key: [8]uint32{0x2b657a8f, 0xfe67575d, 0xaa56d261, 0x30179a97, 0xaefcfff1, 0x9b8eb698, 0x1efe3756, 0xb4ea450c}, + input: "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1", + output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be", + }, + { + length: 56, + nonce: [3]uint32{0xc1dfec38, 0x7d7503d3, 0x9a3e3c66}, + key: [8]uint32{0x8614d8e7, 0xde9b0413, 0x2a48b4fa, 0xcbbde744, 0xad5ddc5e, 0x9144d83e, 0x74d9d617, 0x230bdb45}, + input: "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed", + output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005", + }, + { + length: 63, + nonce: [3]uint32{0xc7e2521c, 0x795499b4, 0xc7946cd7}, + key: [8]uint32{0x53fce774, 0x9a4b53bf, 0x5f614134, 0xa3c39414, 0xa8a07c72, 0x93242311, 0x43aeec99, 0x216deb5a}, + input: "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970", + output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5", + }, + { + length: 66, + nonce: [3]uint32{0x1d41f0a1, 0x7c3b7778, 0x6991eea5}, + key: [8]uint32{0x1f213e39, 0x56261d14, 0x15fc7c2c, 0x21feccc5, 0xa95684c5, 0x26600506, 0xdadcc06b, 0xf2c810b0}, + input: "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5", + output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6", + }, + { + length: 72, + nonce: [3]uint32{0x749f022c, 0xa021dab0, 0x648c2252}, + key: [8]uint32{0xa1ace7b0, 0x567a0ea1, 0x52af13b9, 0xcba30c08, 0xe07a6d74, 0x5c3bca39, 0x85b2ac07, 0x3b5afc0}, + input: "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225", + output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5", + }, + { + length: 74, + nonce: [3]uint32{0x23c16ba8, 0x9fd1cd4e, 0xcb224ecb}, + key: [8]uint32{0xb694404a, 0x86b5f198, 0x10fd1bff, 0x13a84e54, 0xab21e509, 0x7443d764, 0x931b3f1, 0x686e87f2}, + input: "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e", + output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8", + }, + { + length: 81, + nonce: [3]uint32{0xd65f6f29, 0xf3f76219, 0x9a033c9e}, + key: [8]uint32{0xeba017c4, 0x69e0421a, 0x449e2317, 0x29858a11, 0xd0c8523a, 0xa8b0c9a2, 0xab2ca84, 0xaf011a45}, + input: "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943", + output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764", + }, + { + length: 88, + nonce: [3]uint32{0xc70ee56e, 0xe58ec41, 0xafd96f61}, + key: [8]uint32{0x172af2bb, 0x9085d27c, 0x8ca2c44d, 0x8aa148da, 0x290c88b0, 0x88187439, 0x18d54781, 0x633f2cce}, + input: "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d", + output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337", + }, + { + length: 92, + nonce: [3]uint32{0x3006da79, 0x2748051d, 0x72c17cdc}, + key: [8]uint32{0x60cdb7e8, 0xcecbe928, 0xe19b7ab9, 0x30d61537, 0xa0fbc199, 0x897738bf, 0xdd7705a9, 0x3e5c1763}, + input: "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc", + output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548", + }, + { + length: 96, + nonce: [3]uint32{0xfc0fb1ee, 0x414cc60a, 0x4144bd67}, + key: [8]uint32{0x103291c6, 0x822b03b6, 0xd29ab548, 0xc88f3efe, 0x6936056a, 0x28aaa61f, 0xa0df7858, 0xdaa23519}, + input: "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc", + output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30", + }, + { + length: 103, + nonce: [3]uint32{0xc2030c57, 0x1e3b59e1, 0x607ede1a}, + key: [8]uint32{0xd1bac2b5, 0x56a94583, 0x628b479b, 0x3056a51e, 0x69bf8f8f, 0x2df1e03d, 0x4b9d48d2, 0x7df5c379}, + input: "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274", + output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b", + }, + { + length: 109, + nonce: [3]uint32{0xf44dc81f, 0xcf6e03e7, 0xf4966796}, + key: [8]uint32{0xd7b12f4, 0x683f4789, 0xc7828fb4, 0x820fc6a0, 0xc51231eb, 0xe46716d7, 0x4036ef93, 0x26afb96c}, + input: "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192", + output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5", + }, + { + length: 115, + nonce: [3]uint32{0x8d3e461b, 0x7e05c360, 0x3bbbafdd}, + key: [8]uint32{0xf9b917c9, 0x9af89bf7, 0x7decbbc9, 0xe7e5ea7b, 0x9b4aab55, 0x90eff6be, 0xa19b6d90, 0xb9f69b1a}, + input: "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e", + output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe", + }, + { + length: 119, + nonce: [3]uint32{0x871f33f5, 0xe4fee3ba, 0xcb8c1e93}, + key: [8]uint32{0x33124903, 0x7e0287e5, 0xe9d6988f, 0x1962405f, 0x5f21c1b5, 0x2ac695e6, 0x46b200c9, 0x9fda98ba}, + input: "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011", + output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18", + }, + { + length: 120, + nonce: [3]uint32{0xef553ce8, 0xdfe120ea, 0x9a047e3a}, + key: [8]uint32{0xbef479c1, 0x59554f8b, 0xbf97f089, 0x52316f1e, 0x141e428, 0xff26dc04, 0xe10c8f57, 0xa7568a59}, + input: "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2", + output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e", + }, + { + length: 123, + nonce: [3]uint32{0xd98124a0, 0x78cd80aa, 0x3dc55cfc}, + key: [8]uint32{0x2286e41, 0xf13e38e3, 0xf735476b, 0x33c44bfc, 0xd7978797, 0x4a9c4595, 0x6080413, 0x1299fdd8}, + input: "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2", + output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a", + }, + { + length: 127, + nonce: [3]uint32{0x53106b0f, 0xdf11fd81, 0x69d1b6f3}, + key: [8]uint32{0x736b138, 0x55cde194, 0xf8273c1, 0xf7c268e6, 0x61362bd5, 0xbb3cb455, 0x44d3c9fc, 0x7d56d3fd}, + input: "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32", + output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053", + }, + { + length: 130, + nonce: [3]uint32{0x5e90ffbd, 0xa898f173, 0x269f9a88}, + key: [8]uint32{0x5244e05f, 0xf9adbe9b, 0x9e9f54ac, 0x23460046, 0x6782cdea, 0xba982c96, 0xc721506b, 0xed10f7e3}, + input: "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411", + output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef", + }, + { + length: 130, + nonce: [3]uint32{0x308e39e8, 0x9aa4f14f, 0xf511db96}, + key: [8]uint32{0x833b5219, 0x4b82e588, 0x4b2d652c, 0x7c8f6ed7, 0xfe4be863, 0x9d3a50e5, 0xb888099b, 0x9f8d1968}, + input: "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7", + output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9", + }, + { + length: 135, + nonce: [3]uint32{0xa5feca5a, 0x753ac1b4, 0xc5a46609}, + key: [8]uint32{0xabbf4859, 0x828d9bf6, 0xf7f7aa6d, 0x25208ca2, 0xd7a4c0ad, 0x2fdd3282, 0x2bfcb8c2, 0x8389d84b}, + input: "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419", + output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04", + }, + { + length: 135, + nonce: [3]uint32{0x12aa5846, 0x88604f6c, 0xc10d9585}, + key: [8]uint32{0x1491ccd6, 0x602f559d, 0xd4080c06, 0x202fabd, 0xffd3f4f8, 0xbf144c17, 0x88bf3f3c, 0x8083375}, + input: "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1", + output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab", + }, + { + length: 140, + nonce: [3]uint32{0x1c9d70f0, 0xa088a367, 0x4ec24d2b}, + key: [8]uint32{0x494e9775, 0xd07a852, 0xaf8af24a, 0xc65b825c, 0xc5e06780, 0x17fbbace, 0x651d71b5, 0xf548d8ef}, + input: "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9", + output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5", + }, + { + length: 144, + nonce: [3]uint32{0x23067b8b, 0x5b276c6d, 0xaeca6c60}, + key: [8]uint32{0x29d64488, 0x893a2973, 0x32e3b4ef, 0x2af3d5d4, 0x95ec01b, 0xc805b64c, 0x884e8b7d, 0x798d7062}, + input: "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e", + output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60", + }, + { + length: 148, + nonce: [3]uint32{0x2b079658, 0xbdf5da85, 0x8a75450d}, + key: [8]uint32{0x49c9eaa3, 0x62048819, 0x9baacfa5, 0x3870addc, 0x5c682e1, 0xf4f9fff3, 0xa3848e4b, 0xac1ebc1}, + input: "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72", + output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c", + }, + { + length: 148, + nonce: [3]uint32{0x98e8ab8, 0x84d8e77b, 0xbb305841}, + key: [8]uint32{0x46b5f93c, 0xc8b2778d, 0x2cc5278f, 0xd2a3904c, 0x6ce5d4f, 0xc4459e8, 0x4a35c30, 0x2feadc02}, + input: "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db", + output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504", + }, + { + length: 152, + nonce: [3]uint32{0x2e2a6e4a, 0x9a6d488a, 0xf9966cb6}, + key: [8]uint32{0x58903bff, 0xc2be173f, 0xe26128b5, 0xb6b6af53, 0x92f8eeb, 0x38cf3336, 0x7fdf90fb, 0x7ae24b37}, + input: "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e", + output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f", + }, + { + length: 155, + nonce: [3]uint32{0x243e0198, 0x884448c, 0x9a31e760}, + key: [8]uint32{0x37e017bc, 0x9b1e2e90, 0x15679daa, 0xf94a23ee, 0xda86dfe, 0xc3eea84c, 0xdd199799, 0x6eeffb92}, + input: "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e", + output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551", + }, + { + length: 160, + nonce: [3]uint32{0xd24e866d, 0xc59d25d8, 0xfcf623f1}, + key: [8]uint32{0x5f32cca0, 0x4167cac5, 0xc04943ee, 0x507fa1ec, 0xad8fdfc0, 0x6266fa2d, 0x22f05341, 0x8074143e}, + input: "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260", + output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec", + }, + { + length: 167, + nonce: [3]uint32{0x30b61047, 0x810cf901, 0x4d681524}, + key: [8]uint32{0xe51476d0, 0xdf98008d, 0x59dfe69e, 0xdb39166, 0x6c1e4a4a, 0xfb76165e, 0x5180f185, 0x7359fb35}, + input: "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156", + output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98", + }, + { + length: 172, + nonce: [3]uint32{0x42020cbe, 0xad62af90, 0x29e53cd}, + key: [8]uint32{0xabad2095, 0x601ec477, 0x3bc923a1, 0x1edede1a, 0x33612355, 0x285b4858, 0xd3fd6714, 0xe0f4bcc3}, + input: "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7", + output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5", + }, + { + length: 176, + nonce: [3]uint32{0xa8021c8f, 0x667a02c4, 0x7a68b693}, + key: [8]uint32{0xece401c8, 0xfa805a47, 0x6d572fca, 0x9c1c780c, 0x647545e5, 0xd7ef4c11, 0x91dc1e46, 0xba2a694e}, + input: "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc", + output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff", + }, + { + length: 176, + nonce: [3]uint32{0x414e687c, 0xc6fc69c2, 0xd3ca12d3}, + key: [8]uint32{0x1b51cca, 0xbc8455af, 0x3f904842, 0x6042b452, 0xcd4dd164, 0xda83f3f0, 0xff04b972, 0xf972dd0e}, + input: "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9", + output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa", + }, + { + length: 183, + nonce: [3]uint32{0xdd315c1d, 0x2335da98, 0xe0a0da0f}, + key: [8]uint32{0x6419c7d6, 0xd340f42, 0x7af2f4b8, 0x3536cf42, 0x2f68c6fb, 0xac9d855f, 0x7c4d490, 0x9711b1b1}, + input: "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0", + output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48", + }, + { + length: 185, + nonce: [3]uint32{0xebb44f7c, 0xaf14c7dd, 0x4543cd7a}, + key: [8]uint32{0xce71977, 0x99790e86, 0x6510d6dc, 0x37968ae7, 0x2917fb9a, 0x19ef25f, 0xd282d085, 0x6128d043}, + input: "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12", + output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa", + }, + { + length: 187, + nonce: [3]uint32{0x35cb7190, 0x212e9a86, 0xbc423ce4}, + key: [8]uint32{0xfa19cede, 0x576ae8f2, 0x58055dab, 0x91b3355d, 0x69d2501a, 0x736323c2, 0x266c1385, 0x134f4557}, + input: "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc", + output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4", + }, + { + length: 191, + nonce: [3]uint32{0xccc941ac, 0xdba45b02, 0xab0d7ad6}, + key: [8]uint32{0x9b750752, 0xa627090a, 0x967c95f0, 0xf8ff2c3f, 0x69beb97e, 0xa30b99c1, 0xadddc83, 0x443f9baf}, + input: "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab", + output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1", + }, + { + length: 198, + nonce: [3]uint32{0x987e7c58, 0xcc839a94, 0x30952e60}, + key: [8]uint32{0xe34a286f, 0x4adcd996, 0x97168712, 0xa82dde8, 0x14249e5, 0x5e82810b, 0xb4a445e8, 0x9579adb0}, + input: "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5", + output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2", + }, + { + length: 204, + nonce: [3]uint32{0x851f025a, 0xe6f3c800, 0x85ae7530}, + key: [8]uint32{0x2d0dbe47, 0xda05e465, 0x42f6b3b2, 0x7026e79e, 0x9e446680, 0x691df976, 0xf7b23da2, 0xbb3421fa}, + input: "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220", + output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe", + }, + { + length: 210, + nonce: [3]uint32{0xaebfd97f, 0xf583442d, 0x15ab2f1f}, + key: [8]uint32{0xd3d1cf9b, 0xe43187e6, 0x5071a757, 0x412a83b4, 0x3f27716f, 0x17fdc488, 0x271f77ed, 0x6c4bb056}, + input: "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b", + output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564", + }, + { + length: 216, + nonce: [3]uint32{0xf9e973b8, 0x2485a6a7, 0x2ea7dee6}, + key: [8]uint32{0x96edef11, 0x8cf57f26, 0xb6e3a83c, 0x9ef434c6, 0x4607ea48, 0xace87e4d, 0xa0d87475, 0x3a9c9458}, + input: "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a", + output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be", + }, + { + length: 217, + nonce: [3]uint32{0xe3bd4c44, 0xa3b75a31, 0xfe92010f}, + key: [8]uint32{0xdd05ab8b, 0x5ac7cd1, 0xb8113720, 0x53524706, 0x8e0ceea1, 0x52eb23e7, 0x1c85730b, 0xb33914d5}, + input: "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90", + output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd", + }, + { + length: 218, + nonce: [3]uint32{0xcdabfd50, 0xd10d5b99, 0x9e160a85}, + key: [8]uint32{0x8231a4e9, 0x89f33c8b, 0xf96b11b, 0x853cae9d, 0xf6624a33, 0xee9523ee, 0x28bb7853, 0x688ac6f8}, + input: "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069", + output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377", + }, + { + length: 219, + nonce: [3]uint32{0x67de323f, 0xa0442ac9, 0x9d77b1d9}, + key: [8]uint32{0xca8d33d4, 0x834349d9, 0x5e68d581, 0x99a7c30e, 0xdc7f6038, 0x697e8b63, 0x284c2ece, 0xee3e3bfa}, + input: "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745", + output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e", + }, + { + length: 221, + nonce: [3]uint32{0xa36a3d5a, 0x1747a05f, 0x5440eb4}, + key: [8]uint32{0x2d701ee6, 0x143d5a1a, 0xbb67b9ab, 0xabc88ccc, 0x20baad8f, 0x6507e48b, 0xdb1e1b39, 0x9e521d80}, + input: "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95", + output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c", + }, + { + length: 223, + nonce: [3]uint32{0xb92be022, 0x1e1257c7, 0xad7c01e}, + key: [8]uint32{0xca1dbb9c, 0xaadb9504, 0x77b8a95c, 0xc50deb5e, 0x2dbc0fb8, 0x9e654bc2, 0x94d8925a, 0xfe9cfb66}, + input: "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb", + output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da", + }, + { + length: 224, + nonce: [3]uint32{0x5091927, 0x661c75ba, 0xc23dad}, + key: [8]uint32{0x2e00499d, 0xafdc63db, 0xc3c62efb, 0xb4157a19, 0x84ce8b13, 0x85326279, 0x2ee71e9d, 0x318721e4}, + input: "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800", + output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce", + }, + { + length: 227, + nonce: [3]uint32{0x5d6d997c, 0x9d623987, 0x5742de36}, + key: [8]uint32{0x57b2a5ea, 0xc5bdd68b, 0x99c7b0c6, 0x26aea960, 0xba5c75f1, 0xa904cf6b, 0x685031de, 0xa0f0e99}, + input: "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be", + output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35", + }, + { + length: 233, + nonce: [3]uint32{0x75bca707, 0x89f6d1f4, 0x2a6f657a}, + key: [8]uint32{0x949f42cc, 0x2b5d3c48, 0xfe0be473, 0x17ac92aa, 0xbdc9d9dd, 0x74f9df26, 0x26487508, 0x7c7b41a2}, + input: "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab", + output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273", + }, + { + length: 234, + nonce: [3]uint32{0x5003a4f7, 0x40bd8cde, 0xfe35fb25}, + key: [8]uint32{0x576e49d9, 0xe84e9df, 0x9f227a3, 0x437c9de0, 0xc46ac8de, 0x1a6a2d2b, 0x42ab7684, 0x4253fbb6}, + input: "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789", + output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3", + }, + { + length: 237, + nonce: [3]uint32{0xc6ae48ce, 0x26f0906f, 0xfd8ab8bf}, + key: [8]uint32{0x42b82c50, 0x7f519e0d, 0xcbb95098, 0x6f75e532, 0xe2c9f61b, 0x5a4af942, 0x2679777b, 0x6a8e1c9c}, + input: "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9", + output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d", + }, + { + length: 244, + nonce: [3]uint32{0xea38678b, 0xc41eada, 0x3381147b}, + key: [8]uint32{0x268fc2ac, 0x21297e86, 0xdf9ef8cf, 0xd4b45234, 0x2a95c4f2, 0xcec36ce3, 0xd5fa38c9, 0x7dc43790}, + input: "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc", + output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32", + }, + { + length: 250, + nonce: [3]uint32{0x883ac584, 0x8fb8e7d5, 0xdf07de66}, + key: [8]uint32{0xc7747e47, 0x853d88c6, 0xbf9aa631, 0x78f16480, 0x7c248080, 0x15ff973b, 0x31528a40, 0x629686e5}, + input: "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76", + output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21", + }, + { + length: 256, + nonce: [3]uint32{0x79cd7a62, 0xae619be, 0x7d96d236}, + key: [8]uint32{0x7dec8e64, 0x9f12b14, 0x6c70df2a, 0xeae0aa0d, 0x27b1ac14, 0x7a00d833, 0xe63c0aca, 0x189438e2}, + input: "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990", + output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd", + }, + { + length: 268, + nonce: [3]uint32{0xb7581e00, 0x9a1bba92, 0x64356674}, + key: [8]uint32{0xdc2c9fcd, 0x5e50de1a, 0x8546466b, 0xc1b49b21, 0x36a670cd, 0x2887f367, 0x2fbf4300, 0xf90a0374}, + input: "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca", + output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09", + }, + { + length: 305, + nonce: [3]uint32{0x2c641fcb, 0x5170c7e2, 0x62a23688}, + key: [8]uint32{0x5aed5915, 0xc5c4cc18, 0xf0e51574, 0x75d894c6, 0x1b7082d1, 0x5d2ea1db, 0x709fd24, 0xf5f69898}, + input: "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7", + output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942", + }, + { + length: 430, + nonce: [3]uint32{0x99b172cc, 0x91056d0, 0x48057533}, + key: [8]uint32{0xe6cf398e, 0xc3c56066, 0xc5ff194c, 0xf6d2d8c4, 0x6d1d8908, 0x63e62065, 0xcca485cb, 0x1eb03dd6}, + input: "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f", + output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2", + }, + { + length: 449, + nonce: [3]uint32{0x2adb4a6d, 0x33d00c1c, 0x10a0193c}, + key: [8]uint32{0x8bd707df, 0x70212019, 0xdb685581, 0x9cdbd1a3, 0x7db9ff1a, 0x1af119ee, 0xb1d8c0ff, 0x3c4a22cb}, + input: "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae", + output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5", + }, + { + length: 487, + nonce: [3]uint32{0xecf15215, 0x45e31add, 0x56499d31}, + key: [8]uint32{0xf5988496, 0x49bcc2df, 0x7b4ba3c3, 0x5d5138be, 0xd6cb466b, 0xe98c82f8, 0x147d3f27, 0xc82389f0}, + input: "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf", + output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657", + }, + { + length: 511, + nonce: [3]uint32{0xba68c47, 0xbc020097, 0xbf7d14a7}, + key: [8]uint32{0x3bbeedde, 0x6e8f4d6c, 0x6e27cd72, 0x140ff360, 0xc891efa0, 0x4aaa227f, 0x733cfef2, 0x2b51f1f3}, + input: "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0", + output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9", + }, + { + length: 607, + nonce: [3]uint32{0x9419df54, 0x4593f2a, 0x71c06dd6}, + key: [8]uint32{0x7b517740, 0x41e86353, 0xed629408, 0x5fe32cea, 0xb06bc5df, 0xaec9b350, 0xc00c2a6f, 0xb3aaf44f}, + input: "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd", + output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5", + }, + { + length: 682, + nonce: [3]uint32{0x17cebe90, 0xeffe259b, 0xbdf9d4ca}, + key: [8]uint32{0x172d51e8, 0x5b80f5c6, 0xb9c9e438, 0xa56119c0, 0x62212323, 0xf5386589, 0xde7079a3, 0x669e643}, + input: "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322", + output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe", + }, + { + length: 768, + nonce: [3]uint32{0xb1c9bd09, 0xdbe6497d, 0x16c73b95}, + key: [8]uint32{0xbf9d9e5, 0x2eede668, 0x631dca95, 0x4233e36d, 0xd83fe644, 0x99b11f89, 0xef055717, 0x1ae9695f}, + input: "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca", + output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b", + }, + { + length: 828, + nonce: [3]uint32{0xc7e503e, 0xf8110ddf, 0x83316c8c}, + key: [8]uint32{0xfa2d1cd, 0x4fe7f905, 0x2b9e4c1b, 0x115bc881, 0x2922bcc5, 0x3f60aa25, 0x13c26d31, 0x2096af63}, + input: "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a", + output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38", + }, + { + length: 859, + nonce: [3]uint32{0xeb02dac9, 0xa7cba06c, 0xc24764c}, + key: [8]uint32{0xe9414a57, 0xd5e29546, 0x1a5e2f4c, 0x806e4c46, 0x48098d1f, 0x4351ca1a, 0x53ed97c, 0xa6a495ca}, + input: "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220", + output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f", + }, + { + length: 985, + nonce: [3]uint32{0x3c2b47a4, 0xf614c813, 0xa26f7014}, + key: [8]uint32{0x39bd3d18, 0xc9aacd67, 0xcb5485b5, 0x20536a22, 0xbb22ac87, 0x1c9da580, 0x7d996b2e, 0x456fe461}, + input: "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6", + output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec", + }, +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/xor.go b/vendor/golang.org/x/crypto/internal/chacha20/xor.go new file mode 100644 index 0000000..9c5ba0b --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/xor.go @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found src the LICENSE file. + +package chacha20 + +import ( + "runtime" +) + +// Platforms that have fast unaligned 32-bit little endian accesses. +const unaligned = runtime.GOARCH == "386" || + runtime.GOARCH == "amd64" || + runtime.GOARCH == "arm64" || + runtime.GOARCH == "ppc64le" || + runtime.GOARCH == "s390x" + +// xor reads a little endian uint32 from src, XORs it with u and +// places the result in little endian byte order in dst. +func xor(dst, src []byte, u uint32) { + _, _ = src[3], dst[3] // eliminate bounds checks + if unaligned { + // The compiler should optimize this code into + // 32-bit unaligned little endian loads and stores. + // TODO: delete once the compiler does a reliably + // good job with the generic code below. + // See issue #25111 for more details. + v := uint32(src[0]) + v |= uint32(src[1]) << 8 + v |= uint32(src[2]) << 16 + v |= uint32(src[3]) << 24 + v ^= u + dst[0] = byte(v) + dst[1] = byte(v >> 8) + dst[2] = byte(v >> 16) + dst[3] = byte(v >> 24) + } else { + dst[0] = src[0] ^ byte(u) + dst[1] = src[1] ^ byte(u>>8) + dst[2] = src[2] ^ byte(u>>16) + dst[3] = src[3] ^ byte(u>>24) + } +} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go new file mode 100644 index 0000000..f38797b --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go @@ -0,0 +1,32 @@ +// Copyright 2018 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. + +// +build !appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +import "unsafe" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go new file mode 100644 index 0000000..0cc4a8a --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go @@ -0,0 +1,35 @@ +// Copyright 2018 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. + +// +build appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go new file mode 100644 index 0000000..a5b62ff --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go @@ -0,0 +1,50 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle_test + +import ( + "testing" + + "golang.org/x/crypto/internal/subtle" +) + +var a, b [100]byte + +var aliasingTests = []struct { + x, y []byte + anyOverlap, inexactOverlap bool +}{ + {a[:], b[:], false, false}, + {a[:], b[:0], false, false}, + {a[:], b[:50], false, false}, + {a[40:50], a[50:60], false, false}, + {a[40:50], a[60:70], false, false}, + {a[:51], a[50:], true, true}, + {a[:], a[:], true, false}, + {a[:50], a[:60], true, false}, + {a[:], nil, false, false}, + {nil, nil, false, false}, + {a[:], a[:0], false, false}, + {a[:10], a[:10:20], true, false}, + {a[:10], a[5:10:20], true, true}, +} + +func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { + any := subtle.AnyOverlap(x, y) + if any != anyOverlap { + t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) + } + inexact := subtle.InexactOverlap(x, y) + if inexact != inexactOverlap { + t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) + } +} + +func TestAliasing(t *testing.T) { + for i, tt := range aliasingTests { + testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) + testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) + } +} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go index 53ee83c..a98d1bd 100644 --- a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go +++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go @@ -35,6 +35,7 @@ This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. package secretbox // import "golang.org/x/crypto/nacl/secretbox" import ( + "golang.org/x/crypto/internal/subtle" "golang.org/x/crypto/poly1305" "golang.org/x/crypto/salsa20/salsa" ) @@ -87,6 +88,9 @@ func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { copy(poly1305Key[:], firstBlock[:]) ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) + if subtle.AnyOverlap(out, message) { + panic("nacl: invalid buffer overlap") + } // We XOR up to 32 bytes of message with the keystream generated from // the first block. @@ -118,7 +122,7 @@ func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { // Open authenticates and decrypts a box produced by Seal and appends the // message to out, which must not overlap box. The output will be Overhead // bytes smaller than box. -func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { +func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { if len(box) < Overhead { return nil, false } @@ -143,6 +147,9 @@ func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) } ret, out := sliceForAppend(out, len(box)-Overhead) + if subtle.AnyOverlap(out, box) { + panic("nacl: invalid buffer overlap") + } // We XOR up to 32 bytes of box with the keystream generated from // the first block. diff --git a/vendor/golang.org/x/crypto/nacl/sign/sign.go b/vendor/golang.org/x/crypto/nacl/sign/sign.go new file mode 100644 index 0000000..d076270 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/sign/sign.go @@ -0,0 +1,90 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sign signs small messages using public-key cryptography. +// +// Sign uses Ed25519 to sign messages. The length of messages is not hidden. +// Messages should be small because: +// 1. The whole message needs to be held in memory to be processed. +// 2. Using large messages pressures implementations on small machines to process +// plaintext without verifying the signature. This is very dangerous, and this API +// discourages it, but a protocol that uses excessive message sizes might present +// some implementations with no other choice. +// 3. Performance may be improved by working with messages that fit into data caches. +// Thus large amounts of data should be chunked so that each message is small. +// +// This package is not interoperable with the current release of NaCl +// (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However, +// it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well +// as TweetNaCl (https://tweetnacl.cr.yp.to/). +package sign + +import ( + "io" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/internal/subtle" +) + +// Overhead is the number of bytes of overhead when signing a message. +const Overhead = 64 + +// GenerateKey generates a new public/private key pair suitable for use with +// Sign and Open. +func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error) { + pub, priv, err := ed25519.GenerateKey(rand) + if err != nil { + return nil, nil, err + } + publicKey, privateKey = new([32]byte), new([64]byte) + copy((*publicKey)[:], pub) + copy((*privateKey)[:], priv) + return publicKey, privateKey, nil +} + +// Sign appends a signed copy of message to out, which will be Overhead bytes +// longer than the original and must not overlap it. +func Sign(out, message []byte, privateKey *[64]byte) []byte { + sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message) + ret, out := sliceForAppend(out, Overhead+len(message)) + if subtle.AnyOverlap(out, message) { + panic("nacl: invalid buffer overlap") + } + copy(out, sig) + copy(out[Overhead:], message) + return ret +} + +// Open verifies a signed message produced by Sign and appends the message to +// out, which must not overlap the signed message. The output will be Overhead +// bytes smaller than the signed message. +func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) { + if len(signedMessage) < Overhead { + return nil, false + } + if !ed25519.Verify(ed25519.PublicKey((*publicKey)[:]), signedMessage[Overhead:], signedMessage[:Overhead]) { + return nil, false + } + ret, out := sliceForAppend(out, len(signedMessage)-Overhead) + if subtle.AnyOverlap(out, signedMessage) { + panic("nacl: invalid buffer overlap") + } + copy(out, signedMessage[Overhead:]) + return ret, true +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} diff --git a/vendor/golang.org/x/crypto/nacl/sign/sign_test.go b/vendor/golang.org/x/crypto/nacl/sign/sign_test.go new file mode 100644 index 0000000..0a6439a --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/sign/sign_test.go @@ -0,0 +1,74 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sign + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "testing" +) + +var testSignedMessage, _ = hex.DecodeString("26a0a47f733d02ddb74589b6cbd6f64a7dab1947db79395a1a9e00e4c902c0f185b119897b89b248d16bab4ea781b5a3798d25c2984aec833dddab57e0891e0d68656c6c6f20776f726c64") +var testMessage = testSignedMessage[Overhead:] +var testPublicKey [32]byte +var testPrivateKey = [64]byte{ + 0x98, 0x3c, 0x6a, 0xa6, 0x21, 0xcc, 0xbb, 0xb2, 0xa7, 0xe8, 0x97, 0x94, 0xde, 0x5f, 0xf8, 0x11, + 0x8a, 0xf3, 0x33, 0x1a, 0x03, 0x5c, 0x43, 0x99, 0x03, 0x13, 0x2d, 0xd7, 0xb4, 0xc4, 0x8b, 0xb0, + 0xf6, 0x33, 0x20, 0xa3, 0x34, 0x8b, 0x7b, 0xe2, 0xfe, 0xb4, 0xe7, 0x3a, 0x54, 0x08, 0x2d, 0xd7, + 0x0c, 0xb7, 0xc0, 0xe3, 0xbf, 0x62, 0x6c, 0x55, 0xf0, 0x33, 0x28, 0x52, 0xf8, 0x48, 0x7d, 0xfd, +} + +func init() { + copy(testPublicKey[:], testPrivateKey[32:]) +} + +func TestSign(t *testing.T) { + signedMessage := Sign(nil, testMessage, &testPrivateKey) + if !bytes.Equal(signedMessage, testSignedMessage) { + t.Fatalf("signed message did not match, got\n%x\n, expected\n%x", signedMessage, testSignedMessage) + } +} + +func TestOpen(t *testing.T) { + message, ok := Open(nil, testSignedMessage, &testPublicKey) + if !ok { + t.Fatalf("valid signed message not successfully verified") + } + if !bytes.Equal(message, testMessage) { + t.Fatalf("message did not match, got\n%x\n, expected\n%x", message, testMessage) + } + message, ok = Open(nil, testSignedMessage[1:], &testPublicKey) + if ok { + t.Fatalf("invalid signed message successfully verified") + } + + badMessage := make([]byte, len(testSignedMessage)) + copy(badMessage, testSignedMessage) + badMessage[5] ^= 1 + if _, ok := Open(nil, badMessage, &testPublicKey); ok { + t.Fatalf("Open succeeded with a corrupt message") + } + + var badPublicKey [32]byte + copy(badPublicKey[:], testPublicKey[:]) + badPublicKey[5] ^= 1 + if _, ok := Open(nil, testSignedMessage, &badPublicKey); ok { + t.Fatalf("Open succeeded with a corrupt public key") + } +} + +func TestGenerateSignOpen(t *testing.T) { + publicKey, privateKey, _ := GenerateKey(rand.Reader) + signedMessage := Sign(nil, testMessage, privateKey) + message, ok := Open(nil, signedMessage, publicKey) + if !ok { + t.Fatalf("failed to verify signed message") + } + + if !bytes.Equal(message, testMessage) { + t.Fatalf("verified message does not match signed messge, got\n%x\n, expected\n%x", message, testMessage) + } +} diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go index 589dfd3..5edc9c9 100644 --- a/vendor/golang.org/x/crypto/ocsp/ocsp.go +++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go @@ -488,10 +488,6 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon return nil, err } - if len(basicResp.Certificates) > 1 { - return nil, ParseError("OCSP response contains bad number of certificates") - } - if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { return nil, ParseError("OCSP response contains bad number of responses") } @@ -544,6 +540,13 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon } if len(basicResp.Certificates) > 0 { + // Responders should only send a single certificate (if they + // send any) that connects the responder's certificate to the + // original issuer. We accept responses with multiple + // certificates due to a number responders sending them[1], but + // ignore all but the first. + // + // [1] https://github.com/golang/go/issues/21527 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) if err != nil { return nil, err diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go index 744e293..a79a8c1 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -346,22 +346,25 @@ EachPacket: switch pkt := p.(type) { case *packet.UserId: + // Make a new Identity object, that we might wind up throwing away. + // We'll only add it if we get a valid self-signature over this + // userID. current = new(Identity) current.Name = pkt.Id current.UserId = pkt - e.Identities[pkt.Id] = current for { p, err = packets.Next() if err == io.EOF { - return nil, io.ErrUnexpectedEOF + break EachPacket } else if err != nil { return nil, err } sig, ok := p.(*packet.Signature) if !ok { - return nil, errors.StructuralError("user ID packet not followed by self-signature") + packets.Unread(p) + continue EachPacket } if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { @@ -369,9 +372,10 @@ EachPacket: return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) } current.SelfSignature = sig - break + e.Identities[pkt.Id] = current + } else { + current.Signatures = append(current.Signatures, sig) } - current.Signatures = append(current.Signatures, sig) } case *packet.Signature: if pkt.SigType == packet.SigTypeKeyRevocation { @@ -486,7 +490,7 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err } isPrimaryId := true e.Identities[uid.Id] = &Identity{ - Name: uid.Name, + Name: uid.Id, UserId: uid, SelfSignature: &packet.Signature{ CreationTime: currentTime, @@ -500,6 +504,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err IssuerKeyId: &e.PrimaryKey.KeyId, }, } + err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return nil, err + } // If the user passes in a DefaultHash via packet.Config, // set the PreferredHash for the SelfSignature. @@ -507,6 +515,11 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} } + // Likewise for DefaultCipher. + if config != nil && config.DefaultCipher != 0 { + e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} + } + e.Subkeys = make([]Subkey, 1) e.Subkeys[0] = Subkey{ PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), @@ -524,13 +537,16 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err } e.Subkeys[0].PublicKey.IsSubkey = true e.Subkeys[0].PrivateKey.IsSubkey = true - + err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) + if err != nil { + return nil, err + } return e, nil } -// SerializePrivate serializes an Entity, including private key material, to -// the given Writer. For now, it must only be used on an Entity returned from -// NewEntity. +// SerializePrivate serializes an Entity, including private key material, but +// excluding signatures from other entities, to the given Writer. +// Identities and subkeys are re-signed in case they changed since NewEntry. // If config is nil, sensible defaults will be used. func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { err = e.PrivateKey.Serialize(w) @@ -568,8 +584,8 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error return nil } -// Serialize writes the public part of the given Entity to w. (No private -// key material will be output). +// Serialize writes the public part of the given Entity to w, including +// signatures from other entities. No private key material will be output. func (e *Entity) Serialize(w io.Writer) error { err := e.PrimaryKey.Serialize(w) if err != nil { diff --git a/vendor/golang.org/x/crypto/openpgp/keys_test.go b/vendor/golang.org/x/crypto/openpgp/keys_test.go index 76ba13e..d877589 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys_test.go +++ b/vendor/golang.org/x/crypto/openpgp/keys_test.go @@ -29,16 +29,16 @@ func TestKeyExpiry(t *testing.T) { // // So this should select the newest, non-expired encryption key. key, _ := entity.encryptionKey(time1) - if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { - t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id) + if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { + t.Errorf("Expected key %s at time %s, but got key %s", expected, time1.Format(timeFormat), id) } // Once the first encryption subkey has expired, the second should be // selected. time2, _ := time.Parse(timeFormat, "2013-07-09") key, _ = entity.encryptionKey(time2) - if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { - t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id) + if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { + t.Errorf("Expected key %s at time %s, but got key %s", expected, time2.Format(timeFormat), id) } // Once all the keys have expired, nothing should be returned. @@ -105,6 +105,33 @@ func TestGoodCrossSignature(t *testing.T) { } } +func TestRevokedUserID(t *testing.T) { + // This key contains 2 UIDs, one of which is revoked: + // [ultimate] (1) Golang Gopher + // [ revoked] (2) Golang Gopher + keys, err := ReadArmoredKeyRing(bytes.NewBufferString(revokedUserIDKey)) + if err != nil { + t.Fatal(err) + } + + if len(keys) != 1 { + t.Fatal("Failed to read key with a revoked user id") + } + + var identities []*Identity + for _, identity := range keys[0].Identities { + identities = append(identities, identity) + } + + if numIdentities, numExpected := len(identities), 1; numIdentities != numExpected { + t.Errorf("obtained %d identities, expected %d", numIdentities, numExpected) + } + + if identityName, expectedName := identities[0].Name, "Golang Gopher "; identityName != expectedName { + t.Errorf("obtained identity %s expected %s", identityName, expectedName) + } +} + // TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. func TestExternallyRevocableKey(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) @@ -320,6 +347,70 @@ func TestNewEntityWithoutPreferredHash(t *testing.T) { } } +func TestNewEntityCorrectName(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + if len(entity.Identities) != 1 { + t.Fatalf("len(entity.Identities) = %d, want 1", len(entity.Identities)) + } + var got string + for _, i := range entity.Identities { + got = i.Name + } + want := "Golang Gopher (Test Key) " + if got != want { + t.Fatalf("Identity.Name = %q, want %q", got, want) + } +} + +func TestNewEntityWithPreferredSymmetric(t *testing.T) { + c := &packet.Config{ + DefaultCipher: packet.CipherAES256, + } + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredSymmetric) == 0 { + t.Fatal("didn't find a preferred cipher in self signature") + } + if identity.SelfSignature.PreferredSymmetric[0] != uint8(c.DefaultCipher) { + t.Fatalf("Expected preferred cipher to be %d, got %d", uint8(c.DefaultCipher), identity.SelfSignature.PreferredSymmetric[0]) + } + } +} + +func TestNewEntityWithoutPreferredSymmetric(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredSymmetric) != 0 { + t.Fatalf("Expected preferred cipher to be empty but got length %d", len(identity.SelfSignature.PreferredSymmetric)) + } + } +} + +func TestNewEntityPublicSerialization(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + serializedEntity := bytes.NewBuffer(nil) + entity.Serialize(serializedEntity) + + _, err = ReadEntity(packet.NewReader(bytes.NewBuffer(serializedEntity.Bytes()))) + if err != nil { + t.Fatal(err) + } +} + const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" @@ -417,3 +508,42 @@ SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= =vtbN -----END PGP PUBLIC KEY BLOCK-----` + +const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +7qTZOahrETw= +=IKnw +-----END PGP PUBLIC KEY BLOCK-----` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go index 266840d..02b372c 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go @@ -42,12 +42,18 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) { switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) + if err != nil { + return + } case PubKeyAlgoElGamal: e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) if err != nil { return } e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) + if err != nil { + return + } } _, err = consumeAll(r) return @@ -72,7 +78,8 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { // padding oracle attacks. switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes) + k := priv.PrivateKey.(*rsa.PrivateKey) + b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes)) case PubKeyAlgoElGamal: c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go index fee14cf..f2fcf4d 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go @@ -39,39 +39,44 @@ var encryptedKeyPriv = &PrivateKey{ } func TestDecryptingEncryptedKey(t *testing.T) { - const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" - const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" + for i, encryptedKeyHex := range []string{ + "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8", + // MPI can be shorter than the length of the key. + "c18b032a67d68660df41c70103f8e520c52ae9807183c669ce26e772e482dc5d8cf60e6f59316e145be14d2e5221ee69550db1d5618a8cb002a719f1f0b9345bde21536d410ec90ba86cac37748dec7933eb7f9873873b2d61d3321d1cd44535014f6df58f7bc0c7afb5edc38e1a974428997d2f747f9a173bea9ca53079b409517d332df62d805564cffc9be6", + } { + const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" - p, err := Read(readerFromHex(encryptedKeyHex)) - if err != nil { - t.Errorf("error from Read: %s", err) - return - } - ek, ok := p.(*EncryptedKey) - if !ok { - t.Errorf("didn't parse an EncryptedKey, got %#v", p) - return - } + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Errorf("#%d: error from Read: %s", i, err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("#%d: didn't parse an EncryptedKey, got %#v", i, p) + return + } - if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { - t.Errorf("unexpected EncryptedKey contents: %#v", ek) - return - } + if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { + t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) + return + } - err = ek.Decrypt(encryptedKeyPriv, nil) - if err != nil { - t.Errorf("error from Decrypt: %s", err) - return - } + err = ek.Decrypt(encryptedKeyPriv, nil) + if err != nil { + t.Errorf("#%d: error from Decrypt: %s", i, err) + return + } - if ek.CipherFunc != CipherAES256 { - t.Errorf("unexpected EncryptedKey contents: %#v", ek) - return - } + if ek.CipherFunc != CipherAES256 { + t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) + return + } - keyHex := fmt.Sprintf("%x", ek.Key) - if keyHex != expectedKeyHex { - t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("#%d: bad key, got %s want %s", i, keyHex, expectedKeyHex) + } } } @@ -121,7 +126,7 @@ func TestEncryptingEncryptedKey(t *testing.T) { keyHex := fmt.Sprintf("%x", ek.Key) if keyHex != expectedKeyHex { - t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) } } diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go index 3eded93..625bb5a 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/packet.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go @@ -11,10 +11,12 @@ import ( "crypto/aes" "crypto/cipher" "crypto/des" - "golang.org/x/crypto/cast5" - "golang.org/x/crypto/openpgp/errors" + "crypto/rsa" "io" "math/big" + + "golang.org/x/crypto/cast5" + "golang.org/x/crypto/openpgp/errors" ) // readFull is the same as io.ReadFull except that reading zero bytes returns @@ -500,19 +502,17 @@ func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { numBytes := (int(bitLength) + 7) / 8 mpi = make([]byte, numBytes) _, err = readFull(r, mpi) - return -} - -// mpiLength returns the length of the given *big.Int when serialized as an -// MPI. -func mpiLength(n *big.Int) (mpiLengthInBytes int) { - mpiLengthInBytes = 2 /* MPI length */ - mpiLengthInBytes += (n.BitLen() + 7) / 8 + // According to RFC 4880 3.2. we should check that the MPI has no leading + // zeroes (at least when not an encrypted MPI?), but this implementation + // does generate leading zeroes, so we keep accepting them. return } // writeMPI serializes a big integer to w. func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { + // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. + // Implementations seem to be tolerant of them, and stripping them would + // make it complex to guarantee matching re-serialization. _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) if err == nil { _, err = w.Write(mpiBytes) @@ -525,6 +525,18 @@ func writeBig(w io.Writer, i *big.Int) error { return writeMPI(w, uint16(i.BitLen()), i.Bytes()) } +// padToKeySize left-pads a MPI with zeroes to match the length of the +// specified RSA public. +func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { + k := (pub.N.BitLen() + 7) / 8 + if len(b) >= k { + return b + } + bb := make([]byte, k) + copy(bb[len(bb)-len(b):], b) + return bb +} + // CompressionAlgo Represents the different compression algorithms // supported by OpenPGP (except for BZIP2, which is not currently // supported). See Section 9.3 of RFC 4880. diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go index ead2623..fcd5f52 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go @@ -244,7 +244,12 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey } pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) - pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes)) + + // The bit length is 3 (for the 0x04 specifying an uncompressed key) + // plus two field elements (for x and y), which are rounded up to the + // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 + fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 + pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) pk.setFingerPrintAndKeyId() return pk @@ -515,7 +520,7 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) - err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) + err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) if err != nil { return errors.SignatureError("RSA verification failure") } @@ -566,7 +571,7 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) - if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { return errors.SignatureError("RSA verification failure") } return diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go index 7ad7d91..103696e 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go @@ -6,7 +6,10 @@ package packet import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" "encoding/hex" + "math/big" "testing" "time" ) @@ -186,6 +189,29 @@ func TestEcc384Serialize(t *testing.T) { } } +func TestP256KeyID(t *testing.T) { + // Confirm that key IDs are correctly calculated for ECC keys. + ecdsaPub := &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: fromHex("81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6"), + Y: fromHex("5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff"), + } + pub := NewECDSAPublicKey(time.Unix(1297309478, 0), ecdsaPub) + + const want = uint64(0xd01055fbcadd268e) + if pub.KeyId != want { + t.Errorf("want key ID: %x, got %x", want, pub.KeyId) + } +} + +func fromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("bad hex number: " + hex) + } + return n +} + const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" diff --git a/vendor/golang.org/x/crypto/openpgp/read_test.go b/vendor/golang.org/x/crypto/openpgp/read_test.go index 1fbfbac..f5bba30 100644 --- a/vendor/golang.org/x/crypto/openpgp/read_test.go +++ b/vendor/golang.org/x/crypto/openpgp/read_test.go @@ -124,7 +124,7 @@ func checkSignedMessage(t *testing.T, signedHex, expected string) { return } - if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted { + if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.DecryptedWith != (Key{}) { t.Errorf("bad MessageDetails: %#v", md) } diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go index 65a304c..d6dede7 100644 --- a/vendor/golang.org/x/crypto/openpgp/write.go +++ b/vendor/golang.org/x/crypto/openpgp/write.go @@ -164,12 +164,12 @@ func hashToHashId(h crypto.Hash) uint8 { return v } -// Encrypt encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { +// writeAndSign writes the data as a payload package and, optionally, signs +// it. hints contains optional information, that is also encrypted, +// that aids the recipients in processing the message. The resulting +// WriteCloser must be closed after the contents of the file have been +// written. If config is nil, sensible defaults will be used. +func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { signKey, ok := signed.signingKey(config.Now()) @@ -185,6 +185,83 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } + var hash crypto.Hash + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { + hash = h + break + } + } + + // If the hash specified by config is a candidate, we'll use that. + if configuredHash := config.Hash(); configuredHash.Available() { + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { + hash = h + break + } + } + } + + if hash == 0 { + hashId := candidateHashes[0] + name, ok := s2k.HashIdToString(hashId) + if !ok { + name = "#" + strconv.Itoa(int(hashId)) + } + return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") + } + + if signer != nil { + ops := &packet.OnePassSignature{ + SigType: packet.SigTypeBinary, + Hash: hash, + PubKeyAlgo: signer.PubKeyAlgo, + KeyId: signer.KeyId, + IsLast: true, + } + if err := ops.Serialize(payload); err != nil { + return nil, err + } + } + + if hints == nil { + hints = &FileHints{} + } + + w := payload + if signer != nil { + // If we need to write a signature packet after the literal + // data then we need to stop literalData from closing + // encryptedData. + w = noOpCloser{w} + + } + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) + if err != nil { + return nil, err + } + + if signer != nil { + return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil + } + return literalData, nil +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if len(to) == 0 { + return nil, errors.InvalidArgumentError("no encryption recipient provided") + } + // These are the possible ciphers that we'll use for the message. candidateCiphers := []uint8{ uint8(packet.CipherAES128), @@ -241,33 +318,6 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } - var hash crypto.Hash - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { - hash = h - break - } - } - - // If the hash specified by config is a candidate, we'll use that. - if configuredHash := config.Hash(); configuredHash.Available() { - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { - hash = h - break - } - } - } - - if hash == 0 { - hashId := candidateHashes[0] - name, ok := s2k.HashIdToString(hashId) - if !ok { - name = "#" + strconv.Itoa(int(hashId)) - } - return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") - } - symKey := make([]byte, cipher.KeySize()) if _, err := io.ReadFull(config.Random(), symKey); err != nil { return nil, err @@ -279,49 +329,37 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } - encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) if err != nil { return } - if signer != nil { - ops := &packet.OnePassSignature{ - SigType: packet.SigTypeBinary, - Hash: hash, - PubKeyAlgo: signer.PubKeyAlgo, - KeyId: signer.KeyId, - IsLast: true, - } - if err := ops.Serialize(encryptedData); err != nil { - return nil, err - } + return writeAndSign(payload, candidateHashes, signed, hints, config) +} + +// Sign signs a message. The resulting WriteCloser must be closed after the +// contents of the file have been written. hints contains optional information +// that aids the recipients in processing the message. +// If config is nil, sensible defaults will be used. +func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { + if signed == nil { + return nil, errors.InvalidArgumentError("no signer provided") } - if hints == nil { - hints = &FileHints{} + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), } - - w := encryptedData - if signer != nil { - // If we need to write a signature packet after the literal - // data then we need to stop literalData from closing - // encryptedData. - w = noOpCloser{encryptedData} - + defaultHashes := candidateHashes[len(candidateHashes)-1:] + preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes } - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) - if err != nil { - return nil, err - } - - if signer != nil { - return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil - } - return literalData, nil + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) } // signatureWriter hashes the contents of a message while passing it along to diff --git a/vendor/golang.org/x/crypto/openpgp/write_test.go b/vendor/golang.org/x/crypto/openpgp/write_test.go index f2d50a0..cbc8f4d 100644 --- a/vendor/golang.org/x/crypto/openpgp/write_test.go +++ b/vendor/golang.org/x/crypto/openpgp/write_test.go @@ -271,3 +271,92 @@ func TestEncryption(t *testing.T) { } } } + +var testSigningTests = []struct { + keyRingHex string +}{ + { + testKeys1And2PrivateHex, + }, + { + dsaElGamalTestKeysHex, + }, +} + +func TestSigning(t *testing.T) { + for i, test := range testSigningTests { + kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) + + passphrase := []byte("passphrase") + for _, entity := range kring { + if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { + err := entity.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt key", i) + } + } + for _, subkey := range entity.Subkeys { + if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { + err := subkey.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt subkey", i) + } + } + } + } + + signed := kring[0] + + buf := new(bytes.Buffer) + w, err := Sign(buf, signed, nil /* no hints */, nil) + if err != nil { + t.Errorf("#%d: error in Sign: %s", i, err) + continue + } + + const message = "testing" + _, err = w.Write([]byte(message)) + if err != nil { + t.Errorf("#%d: error writing plaintext: %s", i, err) + continue + } + err = w.Close() + if err != nil { + t.Errorf("#%d: error closing WriteCloser: %s", i, err) + continue + } + + md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) + if err != nil { + t.Errorf("#%d: error reading message: %s", i, err) + continue + } + + testTime, _ := time.Parse("2006-01-02", "2013-07-01") + signKey, _ := kring[0].signingKey(testTime) + expectedKeyId := signKey.PublicKey.KeyId + if md.SignedByKeyId != expectedKeyId { + t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) + } + if md.SignedBy == nil { + t.Errorf("#%d: failed to find the signing Entity", i) + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("#%d: error reading contents: %v", i, err) + continue + } + + if string(plaintext) != message { + t.Errorf("#%d: got: %q, want: %q", i, plaintext, message) + } + + if md.SignatureError != nil { + t.Errorf("#%d: signature error: %q", i, md.SignatureError) + } + if md.Signature == nil { + t.Error("signature missing") + } + } +} diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go index 017027f..256bdbb 100644 --- a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go +++ b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go @@ -5,7 +5,6 @@ package poly1305 import ( - "bytes" "encoding/hex" "flag" "testing" @@ -14,80 +13,51 @@ import ( var stressFlag = flag.Bool("stress", false, "run slow stress tests") -var testData = []struct { - in, k, correct []byte -}{ - { - []byte("Hello world!"), - []byte("this is 32-byte key for Poly1305"), - []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, - }, - { - make([]byte, 32), - []byte("this is 32-byte key for Poly1305"), - []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, - }, - { - make([]byte, 2007), - []byte("this is 32-byte key for Poly1305"), - []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, - }, - { - make([]byte, 2007), - make([]byte, 32), - make([]byte, 16), - }, - { - // This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/. - []byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29}, - []byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d}, - []byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14}, - }, - { - // This test generates a result of (2^130-1) % (2^130-5). - []byte{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - { - // This test generates a result of (2^130-6) % (2^130-5). - []byte{ - 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - []byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - }, - { - // This test generates a result of (2^130-5) % (2^130-5). - []byte{ - 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - }, +type test struct { + in string + key string + tag string } -func testSum(t *testing.T, unaligned bool) { - var out [16]byte - var key [32]byte +func (t *test) Input() []byte { + in, err := hex.DecodeString(t.in) + if err != nil { + panic(err) + } + return in +} +func (t *test) Key() [32]byte { + buf, err := hex.DecodeString(t.key) + if err != nil { + panic(err) + } + var key [32]byte + copy(key[:], buf[:32]) + return key +} + +func (t *test) Tag() [16]byte { + buf, err := hex.DecodeString(t.tag) + if err != nil { + panic(err) + } + var tag [16]byte + copy(tag[:], buf[:16]) + return tag +} + +func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) { + var tag [16]byte for i, v := range testData { - in := v.in + in := v.Input() if unaligned { in = unalignBytes(in) } - copy(key[:], v.k) - Sum(&out, in, &key) - if !bytes.Equal(out[:], v.correct) { - t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) + key := v.Key() + sumImpl(&tag, in, &key) + if tag != v.Tag() { + t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:]) } } } @@ -125,8 +95,10 @@ func TestBurnin(t *testing.T) { } } -func TestSum(t *testing.T) { testSum(t, false) } -func TestSumUnaligned(t *testing.T) { testSum(t, true) } +func TestSum(t *testing.T) { testSum(t, false, Sum) } +func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) } +func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) } +func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) } func benchmark(b *testing.B, size int, unaligned bool) { var out [16]byte @@ -146,6 +118,7 @@ func Benchmark64(b *testing.B) { benchmark(b, 64, false) } func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } +func Benchmark2M(b *testing.B) { benchmark(b, 2097152, true) } func unalignBytes(in []byte) []byte { out := make([]byte, len(in)+1) diff --git a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go new file mode 100644 index 0000000..751eec5 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2018 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. + +// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl + +package poly1305 + +// Sum generates an authenticator for msg using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { + sumGeneric(out, msg, key) +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go index b2805a5..c4d59bd 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_ref.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!arm gccgo appengine nacl - package poly1305 import "encoding/binary" -// Sum generates an authenticator for msg using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { +// sumGeneric generates an authenticator for msg using a one-time key and +// puts the 16-byte result into out. This is the generic implementation of +// Sum and should be called if no assembly implementation is available. +func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { var ( h0, h1, h2, h3, h4 uint32 // the hash accumulators r0, r1, r2, r3, r4 uint64 // the r part of the key diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go new file mode 100644 index 0000000..7a266ce --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go @@ -0,0 +1,49 @@ +// Copyright 2018 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. + +// +build s390x,go1.11,!gccgo,!appengine + +package poly1305 + +// hasVectorFacility reports whether the machine supports +// the vector facility (vx). +func hasVectorFacility() bool + +// hasVMSLFacility reports whether the machine supports +// Vector Multiply Sum Logical (VMSL). +func hasVMSLFacility() bool + +var hasVX = hasVectorFacility() +var hasVMSL = hasVMSLFacility() + +// poly1305vx is an assembly implementation of Poly1305 that uses vector +// instructions. It must only be called if the vector facility (vx) is +// available. +//go:noescape +func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// poly1305vmsl is an assembly implementation of Poly1305 that uses vector +// instructions, including VMSL. It must only be called if the vector facility (vx) is +// available and if VMSL is supported. +//go:noescape +func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + if hasVX { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + if hasVMSL && len(m) > 256 { + poly1305vmsl(out, mPtr, uint64(len(m)), key) + } else { + poly1305vx(out, mPtr, uint64(len(m)), key) + } + } else { + sumGeneric(out, m, key) + } +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_s390x.s new file mode 100644 index 0000000..356c07a --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_s390x.s @@ -0,0 +1,400 @@ +// Copyright 2018 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. + +// +build s390x,go1.11,!gccgo,!appengine + +#include "textflag.h" + +// Implementation of Poly1305 using the vector facility (vx). + +// constants +#define MOD26 V0 +#define EX0 V1 +#define EX1 V2 +#define EX2 V3 + +// temporaries +#define T_0 V4 +#define T_1 V5 +#define T_2 V6 +#define T_3 V7 +#define T_4 V8 + +// key (r) +#define R_0 V9 +#define R_1 V10 +#define R_2 V11 +#define R_3 V12 +#define R_4 V13 +#define R5_1 V14 +#define R5_2 V15 +#define R5_3 V16 +#define R5_4 V17 +#define RSAVE_0 R5 +#define RSAVE_1 R6 +#define RSAVE_2 R7 +#define RSAVE_3 R8 +#define RSAVE_4 R9 +#define R5SAVE_1 V28 +#define R5SAVE_2 V29 +#define R5SAVE_3 V30 +#define R5SAVE_4 V31 + +// message block +#define F_0 V18 +#define F_1 V19 +#define F_2 V20 +#define F_3 V21 +#define F_4 V22 + +// accumulator +#define H_0 V23 +#define H_1 V24 +#define H_2 V25 +#define H_3 V26 +#define H_4 V27 + +GLOBL ·keyMask<>(SB), RODATA, $16 +DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f +DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f + +GLOBL ·bswapMask<>(SB), RODATA, $16 +DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 +DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 + +GLOBL ·constants<>(SB), RODATA, $64 +// MOD26 +DATA ·constants<>+0(SB)/8, $0x3ffffff +DATA ·constants<>+8(SB)/8, $0x3ffffff +// EX0 +DATA ·constants<>+16(SB)/8, $0x0006050403020100 +DATA ·constants<>+24(SB)/8, $0x1016151413121110 +// EX1 +DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706 +DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716 +// EX2 +DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d +DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d + +// h = (f*g) % (2**130-5) [partial reduction] +#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ + VMLOF f0, g0, h0 \ + VMLOF f0, g1, h1 \ + VMLOF f0, g2, h2 \ + VMLOF f0, g3, h3 \ + VMLOF f0, g4, h4 \ + VMLOF f1, g54, T_0 \ + VMLOF f1, g0, T_1 \ + VMLOF f1, g1, T_2 \ + VMLOF f1, g2, T_3 \ + VMLOF f1, g3, T_4 \ + VMALOF f2, g53, h0, h0 \ + VMALOF f2, g54, h1, h1 \ + VMALOF f2, g0, h2, h2 \ + VMALOF f2, g1, h3, h3 \ + VMALOF f2, g2, h4, h4 \ + VMALOF f3, g52, T_0, T_0 \ + VMALOF f3, g53, T_1, T_1 \ + VMALOF f3, g54, T_2, T_2 \ + VMALOF f3, g0, T_3, T_3 \ + VMALOF f3, g1, T_4, T_4 \ + VMALOF f4, g51, h0, h0 \ + VMALOF f4, g52, h1, h1 \ + VMALOF f4, g53, h2, h2 \ + VMALOF f4, g54, h3, h3 \ + VMALOF f4, g0, h4, h4 \ + VAG T_0, h0, h0 \ + VAG T_1, h1, h1 \ + VAG T_2, h2, h2 \ + VAG T_3, h3, h3 \ + VAG T_4, h4, h4 + +// carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4 +#define REDUCE(h0, h1, h2, h3, h4) \ + VESRLG $26, h0, T_0 \ + VESRLG $26, h3, T_1 \ + VN MOD26, h0, h0 \ + VN MOD26, h3, h3 \ + VAG T_0, h1, h1 \ + VAG T_1, h4, h4 \ + VESRLG $26, h1, T_2 \ + VESRLG $26, h4, T_3 \ + VN MOD26, h1, h1 \ + VN MOD26, h4, h4 \ + VESLG $2, T_3, T_4 \ + VAG T_3, T_4, T_4 \ + VAG T_2, h2, h2 \ + VAG T_4, h0, h0 \ + VESRLG $26, h2, T_0 \ + VESRLG $26, h0, T_1 \ + VN MOD26, h2, h2 \ + VN MOD26, h0, h0 \ + VAG T_0, h3, h3 \ + VAG T_1, h1, h1 \ + VESRLG $26, h3, T_2 \ + VN MOD26, h3, h3 \ + VAG T_2, h4, h4 + +// expand in0 into d[0] and in1 into d[1] +#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ + VGBM $0x0707, d1 \ // d1=tmp + VPERM in0, in1, EX2, d4 \ + VPERM in0, in1, EX0, d0 \ + VPERM in0, in1, EX1, d2 \ + VN d1, d4, d4 \ + VESRLG $26, d0, d1 \ + VESRLG $30, d2, d3 \ + VESRLG $4, d2, d2 \ + VN MOD26, d0, d0 \ + VN MOD26, d1, d1 \ + VN MOD26, d2, d2 \ + VN MOD26, d3, d3 + +// pack h4:h0 into h1:h0 (no carry) +#define PACK(h0, h1, h2, h3, h4) \ + VESLG $26, h1, h1 \ + VESLG $26, h3, h3 \ + VO h0, h1, h0 \ + VO h2, h3, h2 \ + VESLG $4, h2, h2 \ + VLEIB $7, $48, h1 \ + VSLB h1, h2, h2 \ + VO h0, h2, h0 \ + VLEIB $7, $104, h1 \ + VSLB h1, h4, h3 \ + VO h3, h0, h0 \ + VLEIB $7, $24, h1 \ + VSRLB h1, h4, h1 + +// if h > 2**130-5 then h -= 2**130-5 +#define MOD(h0, h1, t0, t1, t2) \ + VZERO t0 \ + VLEIG $1, $5, t0 \ + VACCQ h0, t0, t1 \ + VAQ h0, t0, t0 \ + VONE t2 \ + VLEIG $1, $-4, t2 \ + VAQ t2, t1, t1 \ + VACCQ h1, t1, t1 \ + VONE t2 \ + VAQ t2, t1, t1 \ + VN h0, t1, t2 \ + VNC t0, t1, t1 \ + VO t1, t2, h0 + +// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305vx(SB), $0-32 + // This code processes up to 2 blocks (32 bytes) per iteration + // using the algorithm described in: + // NEON crypto, Daniel J. Bernstein & Peter Schwabe + // https://cryptojedi.org/papers/neoncrypto-20120320.pdf + LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key + + // load MOD26, EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), MOD26, EX2 + + // setup r + VL (R4), T_0 + MOVD $·keyMask<>(SB), R6 + VL (R6), T_1 + VN T_0, T_1, T_0 + EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4) + + // setup r*5 + VLEIG $0, $5, T_0 + VLEIG $1, $5, T_0 + + // store r (for final block) + VMLOF T_0, R_1, R5SAVE_1 + VMLOF T_0, R_2, R5SAVE_2 + VMLOF T_0, R_3, R5SAVE_3 + VMLOF T_0, R_4, R5SAVE_4 + VLGVG $0, R_0, RSAVE_0 + VLGVG $0, R_1, RSAVE_1 + VLGVG $0, R_2, RSAVE_2 + VLGVG $0, R_3, RSAVE_3 + VLGVG $0, R_4, RSAVE_4 + + // skip r**2 calculation + CMPBLE R3, $16, skip + + // calculate r**2 + MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4) + REDUCE(H_0, H_1, H_2, H_3, H_4) + VLEIG $0, $5, T_0 + VLEIG $1, $5, T_0 + VMLOF T_0, H_1, R5_1 + VMLOF T_0, H_2, R5_2 + VMLOF T_0, H_3, R5_3 + VMLOF T_0, H_4, R5_4 + VLR H_0, R_0 + VLR H_1, R_1 + VLR H_2, R_2 + VLR H_3, R_3 + VLR H_4, R_4 + + // initialize h + VZERO H_0 + VZERO H_1 + VZERO H_2 + VZERO H_3 + VZERO H_4 + +loop: + CMPBLE R3, $32, b2 + VLM (R2), T_0, T_1 + SUB $32, R3 + MOVD $32(R2), R2 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + VLEIB $4, $1, F_4 + VLEIB $12, $1, F_4 + +multiply: + VAG H_0, F_0, F_0 + VAG H_1, F_1, F_1 + VAG H_2, F_2, F_2 + VAG H_3, F_3, F_3 + VAG H_4, F_4, F_4 + MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) + REDUCE(H_0, H_1, H_2, H_3, H_4) + CMPBNE R3, $0, loop + +finish: + // sum vectors + VZERO T_0 + VSUMQG H_0, T_0, H_0 + VSUMQG H_1, T_0, H_1 + VSUMQG H_2, T_0, H_2 + VSUMQG H_3, T_0, H_3 + VSUMQG H_4, T_0, H_4 + + // h may be >= 2*(2**130-5) so we need to reduce it again + REDUCE(H_0, H_1, H_2, H_3, H_4) + + // carry h1->h4 + VESRLG $26, H_1, T_1 + VN MOD26, H_1, H_1 + VAQ T_1, H_2, H_2 + VESRLG $26, H_2, T_2 + VN MOD26, H_2, H_2 + VAQ T_2, H_3, H_3 + VESRLG $26, H_3, T_3 + VN MOD26, H_3, H_3 + VAQ T_3, H_4, H_4 + + // h is now < 2*(2**130-5) + // pack h into h1 (hi) and h0 (lo) + PACK(H_0, H_1, H_2, H_3, H_4) + + // if h > 2**130-5 then h -= 2**130-5 + MOD(H_0, H_1, T_0, T_1, T_2) + + // h += s + MOVD $·bswapMask<>(SB), R5 + VL (R5), T_1 + VL 16(R4), T_0 + VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) + VAQ T_0, H_0, H_0 + VPERM H_0, H_0, T_1, H_0 // reverse bytes (to little) + VST H_0, (R1) + + RET + +b2: + CMPBLE R3, $16, b1 + + // 2 blocks remaining + SUB $17, R3 + VL (R2), T_0 + VLL R3, 16(R2), T_1 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_1 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + CMPBNE R3, $16, 2(PC) + VLEIB $12, $1, F_4 + VLEIB $4, $1, F_4 + + // setup [r²,r] + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, RSAVE_3, R_3 + VLVGG $1, RSAVE_4, R_4 + VPDI $0, R5_1, R5SAVE_1, R5_1 + VPDI $0, R5_2, R5SAVE_2, R5_2 + VPDI $0, R5_3, R5SAVE_3, R5_3 + VPDI $0, R5_4, R5SAVE_4, R5_4 + + MOVD $0, R3 + BR multiply + +skip: + VZERO H_0 + VZERO H_1 + VZERO H_2 + VZERO H_3 + VZERO H_4 + + CMPBEQ R3, $0, finish + +b1: + // 1 block remaining + SUB $1, R3 + VLL R3, (R2), T_0 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_0 + VZERO T_1 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + CMPBNE R3, $16, 2(PC) + VLEIB $4, $1, F_4 + VLEIG $1, $1, R_0 + VZERO R_1 + VZERO R_2 + VZERO R_3 + VZERO R_4 + VZERO R5_1 + VZERO R5_2 + VZERO R5_3 + VZERO R5_4 + + // setup [r, 1] + VLVGG $0, RSAVE_0, R_0 + VLVGG $0, RSAVE_1, R_1 + VLVGG $0, RSAVE_2, R_2 + VLVGG $0, RSAVE_3, R_3 + VLVGG $0, RSAVE_4, R_4 + VPDI $0, R5SAVE_1, R5_1, R5_1 + VPDI $0, R5SAVE_2, R5_2, R5_2 + VPDI $0, R5SAVE_3, R5_3, R5_3 + VPDI $0, R5SAVE_4, R5_4, R5_4 + + MOVD $0, R3 + BR multiply + +TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x40, R1 + BEQ novector + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novector + MOVB $1, ret+0(FP) // have vx + RET + +novector: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s new file mode 100644 index 0000000..e548020 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s @@ -0,0 +1,931 @@ +// Copyright 2018 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. + +// +build s390x,go1.11,!gccgo,!appengine + +#include "textflag.h" + +// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction. + +// constants +#define EX0 V1 +#define EX1 V2 +#define EX2 V3 + +// temporaries +#define T_0 V4 +#define T_1 V5 +#define T_2 V6 +#define T_3 V7 +#define T_4 V8 +#define T_5 V9 +#define T_6 V10 +#define T_7 V11 +#define T_8 V12 +#define T_9 V13 +#define T_10 V14 + +// r**2 & r**4 +#define R_0 V15 +#define R_1 V16 +#define R_2 V17 +#define R5_1 V18 +#define R5_2 V19 +// key (r) +#define RSAVE_0 R7 +#define RSAVE_1 R8 +#define RSAVE_2 R9 +#define R5SAVE_1 R10 +#define R5SAVE_2 R11 + +// message block +#define M0 V20 +#define M1 V21 +#define M2 V22 +#define M3 V23 +#define M4 V24 +#define M5 V25 + +// accumulator +#define H0_0 V26 +#define H1_0 V27 +#define H2_0 V28 +#define H0_1 V29 +#define H1_1 V30 +#define H2_1 V31 + +GLOBL ·keyMask<>(SB), RODATA, $16 +DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f +DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f + +GLOBL ·bswapMask<>(SB), RODATA, $16 +DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 +DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 + +GLOBL ·constants<>(SB), RODATA, $48 +// EX0 +DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+8(SB)/8, $0x0000050403020100 +// EX1 +DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+24(SB)/8, $0x00000a0908070605 +// EX2 +DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b + +GLOBL ·c<>(SB), RODATA, $48 +// EX0 +DATA ·c<>+0(SB)/8, $0x0000050403020100 +DATA ·c<>+8(SB)/8, $0x0000151413121110 +// EX1 +DATA ·c<>+16(SB)/8, $0x00000a0908070605 +DATA ·c<>+24(SB)/8, $0x00001a1918171615 +// EX2 +DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b +DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b + +GLOBL ·reduce<>(SB), RODATA, $32 +// 44 bit +DATA ·reduce<>+0(SB)/8, $0x0 +DATA ·reduce<>+8(SB)/8, $0xfffffffffff +// 42 bit +DATA ·reduce<>+16(SB)/8, $0x0 +DATA ·reduce<>+24(SB)/8, $0x3ffffffffff + +// h = (f*g) % (2**130-5) [partial reduction] +// uses T_0...T_9 temporary registers +// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 +// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2 +#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ + \ // Eliminate the dependency for the last 2 VMSLs + VMSLG m02_0, r_2, m4_2, m4_2 \ + VMSLG m13_0, r_2, m5_2, m5_2 \ // 8 VMSLs pipelined + VMSLG m02_0, r_0, m4_0, m4_0 \ + VMSLG m02_1, r5_2, V0, T_0 \ + VMSLG m02_0, r_1, m4_1, m4_1 \ + VMSLG m02_1, r_0, V0, T_1 \ + VMSLG m02_1, r_1, V0, T_2 \ + VMSLG m02_2, r5_1, V0, T_3 \ + VMSLG m02_2, r5_2, V0, T_4 \ + VMSLG m13_0, r_0, m5_0, m5_0 \ + VMSLG m13_1, r5_2, V0, T_5 \ + VMSLG m13_0, r_1, m5_1, m5_1 \ + VMSLG m13_1, r_0, V0, T_6 \ + VMSLG m13_1, r_1, V0, T_7 \ + VMSLG m13_2, r5_1, V0, T_8 \ + VMSLG m13_2, r5_2, V0, T_9 \ + VMSLG m02_2, r_0, m4_2, m4_2 \ + VMSLG m13_2, r_0, m5_2, m5_2 \ + VAQ m4_0, T_0, m02_0 \ + VAQ m4_1, T_1, m02_1 \ + VAQ m5_0, T_5, m13_0 \ + VAQ m5_1, T_6, m13_1 \ + VAQ m02_0, T_3, m02_0 \ + VAQ m02_1, T_4, m02_1 \ + VAQ m13_0, T_8, m13_0 \ + VAQ m13_1, T_9, m13_1 \ + VAQ m4_2, T_2, m02_2 \ + VAQ m5_2, T_7, m13_2 \ + +// SQUARE uses three limbs of r and r_2*5 to output square of r +// uses T_1, T_5 and T_7 temporary registers +// input: r_0, r_1, r_2, r5_2 +// temp: TEMP0, TEMP1, TEMP2 +// output: p0, p1, p2 +#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \ + VMSLG r_0, r_0, p0, p0 \ + VMSLG r_1, r5_2, V0, TEMP0 \ + VMSLG r_2, r5_2, p1, p1 \ + VMSLG r_0, r_1, V0, TEMP1 \ + VMSLG r_1, r_1, p2, p2 \ + VMSLG r_0, r_2, V0, TEMP2 \ + VAQ TEMP0, p0, p0 \ + VAQ TEMP1, p1, p1 \ + VAQ TEMP2, p2, p2 \ + VAQ TEMP0, p0, p0 \ + VAQ TEMP1, p1, p1 \ + VAQ TEMP2, p2, p2 \ + +// carry h0->h1->h2->h0 || h3->h4->h5->h3 +// uses T_2, T_4, T_5, T_7, T_8, T_9 +// t6, t7, t8, t9, t10, t11 +// input: h0, h1, h2, h3, h4, h5 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 +// output: h0, h1, h2, h3, h4, h5 +#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \ + VLM (R12), t6, t7 \ // 44 and 42 bit clear mask + VLEIB $7, $0x28, t10 \ // 5 byte shift mask + VREPIB $4, t8 \ // 4 bit shift mask + VREPIB $2, t11 \ // 2 bit shift mask + VSRLB t10, h0, t0 \ // h0 byte shift + VSRLB t10, h1, t1 \ // h1 byte shift + VSRLB t10, h2, t2 \ // h2 byte shift + VSRLB t10, h3, t3 \ // h3 byte shift + VSRLB t10, h4, t4 \ // h4 byte shift + VSRLB t10, h5, t5 \ // h5 byte shift + VSRL t8, t0, t0 \ // h0 bit shift + VSRL t8, t1, t1 \ // h2 bit shift + VSRL t11, t2, t2 \ // h2 bit shift + VSRL t8, t3, t3 \ // h3 bit shift + VSRL t8, t4, t4 \ // h4 bit shift + VESLG $2, t2, t9 \ // h2 carry x5 + VSRL t11, t5, t5 \ // h5 bit shift + VN t6, h0, h0 \ // h0 clear carry + VAQ t2, t9, t2 \ // h2 carry x5 + VESLG $2, t5, t9 \ // h5 carry x5 + VN t6, h1, h1 \ // h1 clear carry + VN t7, h2, h2 \ // h2 clear carry + VAQ t5, t9, t5 \ // h5 carry x5 + VN t6, h3, h3 \ // h3 clear carry + VN t6, h4, h4 \ // h4 clear carry + VN t7, h5, h5 \ // h5 clear carry + VAQ t0, h1, h1 \ // h0->h1 + VAQ t3, h4, h4 \ // h3->h4 + VAQ t1, h2, h2 \ // h1->h2 + VAQ t4, h5, h5 \ // h4->h5 + VAQ t2, h0, h0 \ // h2->h0 + VAQ t5, h3, h3 \ // h5->h3 + VREPG $1, t6, t6 \ // 44 and 42 bit masks across both halves + VREPG $1, t7, t7 \ + VSLDB $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5] + VSLDB $8, h1, h1, h1 \ + VSLDB $8, h2, h2, h2 \ + VO h0, h3, h3 \ + VO h1, h4, h4 \ + VO h2, h5, h5 \ + VESRLG $44, h3, t0 \ // 44 bit shift right + VESRLG $44, h4, t1 \ + VESRLG $42, h5, t2 \ + VN t6, h3, h3 \ // clear carry bits + VN t6, h4, h4 \ + VN t7, h5, h5 \ + VESLG $2, t2, t9 \ // multiply carry by 5 + VAQ t9, t2, t2 \ + VAQ t0, h4, h4 \ + VAQ t1, h5, h5 \ + VAQ t2, h3, h3 \ + +// carry h0->h1->h2->h0 +// input: h0, h1, h2 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8 +// output: h0, h1, h2 +#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \ + VLEIB $7, $0x28, t3 \ // 5 byte shift mask + VREPIB $4, t4 \ // 4 bit shift mask + VREPIB $2, t7 \ // 2 bit shift mask + VGBM $0x003F, t5 \ // mask to clear carry bits + VSRLB t3, h0, t0 \ + VSRLB t3, h1, t1 \ + VSRLB t3, h2, t2 \ + VESRLG $4, t5, t5 \ // 44 bit clear mask + VSRL t4, t0, t0 \ + VSRL t4, t1, t1 \ + VSRL t7, t2, t2 \ + VESRLG $2, t5, t6 \ // 42 bit clear mask + VESLG $2, t2, t8 \ + VAQ t8, t2, t2 \ + VN t5, h0, h0 \ + VN t5, h1, h1 \ + VN t6, h2, h2 \ + VAQ t0, h1, h1 \ + VAQ t1, h2, h2 \ + VAQ t2, h0, h0 \ + VSRLB t3, h0, t0 \ + VSRLB t3, h1, t1 \ + VSRLB t3, h2, t2 \ + VSRL t4, t0, t0 \ + VSRL t4, t1, t1 \ + VSRL t7, t2, t2 \ + VN t5, h0, h0 \ + VN t5, h1, h1 \ + VESLG $2, t2, t8 \ + VN t6, h2, h2 \ + VAQ t0, h1, h1 \ + VAQ t8, t2, t2 \ + VAQ t1, h2, h2 \ + VAQ t2, h0, h0 \ + +// expands two message blocks into the lower halfs of the d registers +// moves the contents of the d registers into upper halfs +// input: in1, in2, d0, d1, d2, d3, d4, d5 +// temp: TEMP0, TEMP1, TEMP2, TEMP3 +// output: d0, d1, d2, d3, d4, d5 +#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \ + VGBM $0xff3f, TEMP0 \ + VGBM $0xff1f, TEMP1 \ + VESLG $4, d1, TEMP2 \ + VESLG $4, d4, TEMP3 \ + VESRLG $4, TEMP0, TEMP0 \ + VPERM in1, d0, EX0, d0 \ + VPERM in2, d3, EX0, d3 \ + VPERM in1, d2, EX2, d2 \ + VPERM in2, d5, EX2, d5 \ + VPERM in1, TEMP2, EX1, d1 \ + VPERM in2, TEMP3, EX1, d4 \ + VN TEMP0, d0, d0 \ + VN TEMP0, d3, d3 \ + VESRLG $4, d1, d1 \ + VESRLG $4, d4, d4 \ + VN TEMP1, d2, d2 \ + VN TEMP1, d5, d5 \ + VN TEMP0, d1, d1 \ + VN TEMP0, d4, d4 \ + +// expands one message block into the lower halfs of the d registers +// moves the contents of the d registers into upper halfs +// input: in, d0, d1, d2 +// temp: TEMP0, TEMP1, TEMP2 +// output: d0, d1, d2 +#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \ + VGBM $0xff3f, TEMP0 \ + VESLG $4, d1, TEMP2 \ + VGBM $0xff1f, TEMP1 \ + VPERM in, d0, EX0, d0 \ + VESRLG $4, TEMP0, TEMP0 \ + VPERM in, d2, EX2, d2 \ + VPERM in, TEMP2, EX1, d1 \ + VN TEMP0, d0, d0 \ + VN TEMP1, d2, d2 \ + VESRLG $4, d1, d1 \ + VN TEMP0, d1, d1 \ + +// pack h2:h0 into h1:h0 (no carry) +// input: h0, h1, h2 +// output: h0, h1, h2 +#define PACK(h0, h1, h2) \ + VMRLG h1, h2, h2 \ // copy h1 to upper half h2 + VESLG $44, h1, h1 \ // shift limb 1 44 bits, leaving 20 + VO h0, h1, h0 \ // combine h0 with 20 bits from limb 1 + VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1 + VLEIG $1, $0, h1 \ // clear h2 stuff from lower half of h1 + VO h0, h1, h0 \ // h0 now has 88 bits (limb 0 and 1) + VLEIG $0, $0, h2 \ // clear upper half of h2 + VESRLG $40, h2, h1 \ // h1 now has upper two bits of result + VLEIB $7, $88, h1 \ // for byte shift (11 bytes) + VSLB h1, h2, h2 \ // shift h2 11 bytes to the left + VO h0, h2, h0 \ // combine h0 with 20 bits from limb 1 + VLEIG $0, $0, h1 \ // clear upper half of h1 + +// if h > 2**130-5 then h -= 2**130-5 +// input: h0, h1 +// temp: t0, t1, t2 +// output: h0 +#define MOD(h0, h1, t0, t1, t2) \ + VZERO t0 \ + VLEIG $1, $5, t0 \ + VACCQ h0, t0, t1 \ + VAQ h0, t0, t0 \ + VONE t2 \ + VLEIG $1, $-4, t2 \ + VAQ t2, t1, t1 \ + VACCQ h1, t1, t1 \ + VONE t2 \ + VAQ t2, t1, t1 \ + VN h0, t1, t2 \ + VNC t0, t1, t1 \ + VO t1, t2, h0 \ + +// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305vmsl(SB), $0-32 + // This code processes 6 + up to 4 blocks (32 bytes) per iteration + // using the algorithm described in: + // NEON crypto, Daniel J. Bernstein & Peter Schwabe + // https://cryptojedi.org/papers/neoncrypto-20120320.pdf + // And as moddified for VMSL as described in + // Accelerating Poly1305 Cryptographic Message Authentication on the z14 + // O'Farrell et al, CASCON 2017, p48-55 + // https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht + + LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key + VZERO V0 // c + + // load EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 // c + + // setup r + VL (R4), T_0 + MOVD $·keyMask<>(SB), R6 + VL (R6), T_1 + VN T_0, T_1, T_0 + VZERO T_2 // limbs for r + VZERO T_3 + VZERO T_4 + EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7) + + // T_2, T_3, T_4: [0, r] + + // setup r*20 + VLEIG $0, $0, T_0 + VLEIG $1, $20, T_0 // T_0: [0, 20] + VZERO T_5 + VZERO T_6 + VMSLG T_0, T_3, T_5, T_5 + VMSLG T_0, T_4, T_6, T_6 + + // store r for final block in GR + VLGVG $1, T_2, RSAVE_0 // c + VLGVG $1, T_3, RSAVE_1 // c + VLGVG $1, T_4, RSAVE_2 // c + VLGVG $1, T_5, R5SAVE_1 // c + VLGVG $1, T_6, R5SAVE_2 // c + + // initialize h + VZERO H0_0 + VZERO H1_0 + VZERO H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + // initialize pointer for reduce constants + MOVD $·reduce<>(SB), R12 + + // calculate r**2 and 20*(r**2) + VZERO R_0 + VZERO R_1 + VZERO R_2 + SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7) + REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1) + VZERO R5_1 + VZERO R5_2 + VMSLG T_0, R_1, R5_1, R5_1 + VMSLG T_0, R_2, R5_2, R5_2 + + // skip r**4 calculation if 3 blocks or less + CMPBLE R3, $48, b4 + + // calculate r**4 and 20*(r**4) + VZERO T_8 + VZERO T_9 + VZERO T_10 + SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7) + REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1) + VZERO T_2 + VZERO T_3 + VMSLG T_0, T_9, T_2, T_2 + VMSLG T_0, T_10, T_3, T_3 + + // put r**2 to the right and r**4 to the left of R_0, R_1, R_2 + VSLDB $8, T_8, T_8, T_8 + VSLDB $8, T_9, T_9, T_9 + VSLDB $8, T_10, T_10, T_10 + VSLDB $8, T_2, T_2, T_2 + VSLDB $8, T_3, T_3, T_3 + + VO T_8, R_0, R_0 + VO T_9, R_1, R_1 + VO T_10, R_2, R_2 + VO T_2, R5_1, R5_1 + VO T_3, R5_2, R5_2 + + CMPBLE R3, $80, load // less than or equal to 5 blocks in message + + // 6(or 5+1) blocks + SUB $81, R3 + VLM (R2), M0, M4 + VLL R3, 80(R2), M5 + ADD $1, R3 + MOVBZ $1, R0 + CMPBGE R3, $16, 2(PC) + VLVGB R3, R0, M5 + MOVD $96(R2), R2 + EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + VLEIB $2, $1, H2_0 + VLEIB $2, $1, H2_1 + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO T_4 + VZERO T_10 + EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3) + VLR T_4, M4 + VLEIB $10, $1, M2 + CMPBLT R3, $16, 2(PC) + VLEIB $10, $1, T_10 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + SUB $16, R3 + CMPBLE R3, $0, square + +load: + // load EX0, EX1 and EX2 + MOVD $·c<>(SB), R5 + VLM (R5), EX0, EX2 + +loop: + CMPBLE R3, $64, add // b4 // last 4 or less blocks left + + // next 4 full blocks + VLM (R2), M2, M5 + SUB $64, R3 + MOVD $64(R2), R2 + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9) + + // expacc in-lined to create [m2, m3] limbs + VGBM $0x3f3f, T_0 // 44 bit clear mask + VGBM $0x1f1f, T_1 // 40 bit clear mask + VPERM M2, M3, EX0, T_3 + VESRLG $4, T_0, T_0 // 44 bit clear mask ready + VPERM M2, M3, EX1, T_4 + VPERM M2, M3, EX2, T_5 + VN T_0, T_3, T_3 + VESRLG $4, T_4, T_4 + VN T_1, T_5, T_5 + VN T_0, T_4, T_4 + VMRHG H0_1, T_3, H0_0 + VMRHG H1_1, T_4, H1_0 + VMRHG H2_1, T_5, H2_0 + VMRLG H0_1, T_3, H0_1 + VMRLG H1_1, T_4, H1_1 + VMRLG H2_1, T_5, H2_1 + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + VPERM M4, M5, EX0, T_3 + VPERM M4, M5, EX1, T_4 + VPERM M4, M5, EX2, T_5 + VN T_0, T_3, T_3 + VESRLG $4, T_4, T_4 + VN T_1, T_5, T_5 + VN T_0, T_4, T_4 + VMRHG V0, T_3, M0 + VMRHG V0, T_4, M1 + VMRHG V0, T_5, M2 + VMRLG V0, T_3, M3 + VMRLG V0, T_4, M4 + VMRLG V0, T_5, M5 + VLEIB $10, $1, M2 + VLEIB $10, $1, M5 + + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + CMPBNE R3, $0, loop + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + // load EX0, EX1, EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + // sum vectors + VAQ H0_0, H0_1, H0_0 + VAQ H1_0, H1_1, H1_0 + VAQ H2_0, H2_1, H2_0 + + // h may be >= 2*(2**130-5) so we need to reduce it again + // M0...M4 are used as temps here + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + +next: // carry h1->h2 + VLEIB $7, $0x28, T_1 + VREPIB $4, T_2 + VGBM $0x003F, T_3 + VESRLG $4, T_3 + + // byte shift + VSRLB T_1, H1_0, T_4 + + // bit shift + VSRL T_2, T_4, T_4 + + // clear h1 carry bits + VN T_3, H1_0, H1_0 + + // add carry + VAQ T_4, H2_0, H2_0 + + // h is now < 2*(2**130-5) + // pack h into h1 (hi) and h0 (lo) + PACK(H0_0, H1_0, H2_0) + + // if h > 2**130-5 then h -= 2**130-5 + MOD(H0_0, H1_0, T_0, T_1, T_2) + + // h += s + MOVD $·bswapMask<>(SB), R5 + VL (R5), T_1 + VL 16(R4), T_0 + VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) + VAQ T_0, H0_0, H0_0 + VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little) + VST H0_0, (R1) + RET + +add: + // load EX0, EX1, EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + CMPBLE R3, $64, b4 + +b4: + CMPBLE R3, $48, b3 // 3 blocks or less + + // 4(3+1) blocks remaining + SUB $49, R3 + VLM (R2), M0, M2 + VLL R3, 48(R2), M3 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M3 + MOVD $64(R2), R2 + EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + VZERO M0 + VZERO M1 + VZERO M4 + VZERO M5 + VZERO T_4 + VZERO T_10 + EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3) + VLR T_4, M2 + VLEIB $10, $1, M4 + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_10 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + SUB $16, R3 + CMPBLE R3, $0, square // this condition must always hold true! + +b3: + CMPBLE R3, $32, b2 + + // 3 blocks remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5) + + SUB $33, R3 + VLM (R2), M0, M1 + VLL R3, 32(R2), M2 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M2 + + // H += m0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6) + VLEIB $10, $1, T_3 + VAG H0_0, T_1, H0_0 + VAG H1_0, T_2, H1_0 + VAG H2_0, T_3, H2_0 + + VZERO M0 + VZERO M3 + VZERO M4 + VZERO M5 + VZERO T_10 + + // (H+m0)*r + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9) + + // H += m1 + VZERO V0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6) + VLEIB $10, $1, T_3 + VAQ H0_0, T_1, H0_0 + VAQ H1_0, T_2, H1_0 + VAQ H2_0, T_3, H2_0 + REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) + + // [H, m2] * [r**2, r] + EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3) + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, H2_0 + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10) + SUB $16, R3 + CMPBLE R3, $0, next // this condition must always hold true! + +b2: + CMPBLE R3, $16, b1 + + // 2 blocks remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + // move h to the left and 0s at the right + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + + // get message blocks and append 1 to start + SUB $17, R3 + VL (R2), M0 + VLL R3, 16(R2), M1 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M1 + VZERO T_6 + VZERO T_7 + VZERO T_8 + EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3) + EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3) + VLEIB $2, $1, T_8 + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_8 + + // add [m0, m1] to h + VAG H0_0, T_6, H0_0 + VAG H1_0, T_7, H1_0 + VAG H2_0, T_8, H2_0 + + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + VZERO T_10 + VZERO M0 + + // at this point R_0 .. R5_2 look like [r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) + SUB $16, R3, R3 + CMPBLE R3, $0, next + +b1: + CMPBLE R3, $0, next + + // 1 block remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + + // set up [0, m0] limbs + SUB $1, R3 + VLL R3, (R2), M0 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m] + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_3 + + // h+m0 + VAQ H0_0, T_1, H0_0 + VAQ H1_0, T_2, H1_0 + VAQ H2_0, T_3, H2_0 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + + BR next + +square: + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // (h0*r**2) + (h1*r) + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + BR next + +TEXT ·hasVMSLFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x01, R1 + BEQ novmsl + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novmsl + MOVB $1, ret+0(FP) // have vx + RET + +novmsl: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/poly1305/vectors_test.go b/vendor/golang.org/x/crypto/poly1305/vectors_test.go new file mode 100644 index 0000000..18d7ff8 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/vectors_test.go @@ -0,0 +1,2943 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package poly1305 + +var testData = [...]test{ + // edge cases + { + // see https://go-review.googlesource.com/#/c/30101/ + key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000", + tag: "6dc18b8c344cd79927118bbe84b7f314", + in: "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5) + in: "ffffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5) + in: "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "faffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + { + key: "0100000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5) + in: "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "fbffffffffffffffffffffffffffffff" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + }, + // original smoke tests + { + key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + tag: "a6f745008f81c916a20dcc74eef2b2f0", + in: "48656c6c6f20776f726c6421", + }, + { + key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + tag: "49ec78090e481ec6c26b33b91ccc0307", + in: "0000000000000000000000000000000000000000000000000000000000000000", + }, + { + key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + tag: "da84bcab02676c38cdb015604274c2aa", + in: "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000", + }, + { + key: "0000000000000000000000000000000000000000000000000000000000000000", + tag: "00000000000000000000000000000000", + in: "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000", + }, + // randomly generated + { + key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649", + tag: "9566c74d10037c4d7bbb0407d1e2c649", + in: "", + }, + { + key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999", + tag: "eaa270caaa12faa39b797374a4b8a420", + in: "eb", + }, + { + key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f", + tag: "dbea66e1da48a8f822887c6162c2acf1", + in: "b90b", + }, + { + key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525", + tag: "6ac09aaa88c32ee95a7198376f16abdb", + in: "3fec73", + }, + { + key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592", + tag: "b1443487f97fe340b04a74719ed4de68", + in: "1e668a5b", + }, + { + key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c", + tag: "7463be0f9d99a5348039e4afcbf4019c", + in: "c3dbd968b0", + }, + { + key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb", + tag: "2edaee3bcf303fd05609e131716f8157", + in: "e0255aa5b7d4", + }, + { + key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6", + tag: "965f18767420c1d94a4ef657e8d15e1e", + in: "924b98cbf8713f", + }, + { + key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933", + tag: "2bf4a33287dd6d87e1ed4282f7342b6a", + in: "3ff993933bea6f5b", + }, + { + key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3", + tag: "c5e987b60373a48893c5af30acf2471f", + in: "b539eb1e5849c6077d", + }, + { + key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8", + tag: "19f0f640b309d168ea1b480e6a4faee5", + in: "fa7311e4d7defa922daa", + }, + { + key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd", + tag: "de75e5565d97834b9fa84ad568d31359", + in: "f8883a0ad8be9c3978b048", + }, + { + key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e", + tag: "de184a5a9b826aa203c5c017986d6690", + in: "4da6430105220d0b29688b73", + }, + { + key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979", + tag: "7478f18d9684905aa5d1a34ee67e4c84", + in: "e4d60f26686d9bf2fb26c901ff", + }, + { + key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341", + tag: "3b2008a9c52b5308f5538b789ab5506f", + in: "79d3af4491a369012db92d184fc3", + }, + { + key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009", + tag: "71c8e76a67a505b7370b562ba15ba032", + in: "79d1830356f2a54c3deab2a4b4475d", + }, + { + key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae", + tag: "1dc895f74f866bdb3edf6c4430829c1c", + in: "f78ae151c00755925836b7075885650c", + }, + { + key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827", + tag: "afca2b3ba7b0e1a928001966883e9b16", + in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" + + "bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" + + "14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" + + "28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" + + "5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" + + "e4b38eaf3f", + }, + { + key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab", + tag: "6f2a09aa76c9b76774e31ec02dcf7991", + in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" + + "d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" + + "10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" + + "d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" + + "cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" + + "56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" + + "22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" + + "21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" + + "d797ddea", + }, + { + key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd", + tag: "27381e3fc2a356103fb796f107d826e7", + in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" + + "bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" + + "03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" + + "47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" + + "228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" + + "7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" + + "70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" + + "e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" + + "568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" + + "a6", + }, + { + key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641", + tag: "0173965669fb9de88d38a827a0271271", + in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" + + "99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" + + "c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" + + "2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" + + "4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" + + "226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" + + "9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" + + "152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" + + "b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" + + "18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" + + "d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" + + "90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" + + "9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" + + "0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" + + "ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" + + "d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" + + "41723470bf24a865837c", + }, + { + key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007", + tag: "1eb0cdad9237905250d30a24fe172a34", + in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" + + "090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" + + "3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" + + "b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" + + "afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" + + "5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" + + "e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" + + "ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" + + "10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" + + "410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" + + "c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" + + "eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" + + "36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" + + "14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" + + "05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" + + "de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" + + "a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" + + "9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" + + "9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" + + "1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" + + "aaba160cd6", + }, + { + key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7", + tag: "2e619d8ea81b77484e4fddeb29844e4b", + in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" + + "cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" + + "a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" + + "ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" + + "5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" + + "53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" + + "f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" + + "b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" + + "811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" + + "2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" + + "e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" + + "d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" + + "548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" + + "fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" + + "c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" + + "0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" + + "e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" + + "da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" + + "66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" + + "2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" + + "9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" + + "402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" + + "42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" + + "94df", + }, + { + key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f", + tag: "0d57b8cbea8090df0541354673dcb4e0", + in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" + + "1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" + + "f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" + + "c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" + + "c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" + + "ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" + + "12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" + + "5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" + + "293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" + + "0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" + + "5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" + + "f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" + + "f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" + + "0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" + + "e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" + + "8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" + + "d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" + + "5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" + + "7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" + + "b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" + + "058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" + + "a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" + + "f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" + + "5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" + + "fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" + + "e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" + + "16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" + + "177620b28ca6f56a716f8cb384", + }, + { + key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003", + tag: "c6e59044cefc43ee681c3eed872d02b3", + in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" + + "b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" + + "3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" + + "0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" + + "dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" + + "c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" + + "0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" + + "78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" + + "3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" + + "5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" + + "86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" + + "b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" + + "48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" + + "44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" + + "3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" + + "41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" + + "db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" + + "2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" + + "8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" + + "e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" + + "14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" + + "b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" + + "4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" + + "3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" + + "4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" + + "0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" + + "b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" + + "89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89", + }, + { + key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8", + tag: "6e50e70411201378c8d67857d7b631d2", + in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" + + "0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" + + "04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" + + "f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" + + "2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" + + "614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" + + "ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" + + "0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" + + "6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" + + "d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" + + "4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" + + "8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" + + "b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" + + "1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" + + "e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" + + "522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" + + "2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" + + "1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" + + "b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" + + "e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" + + "c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" + + "ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" + + "0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" + + "03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" + + "367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" + + "d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" + + "59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" + + "bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" + + "fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" + + "0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" + + "e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" + + "7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" + + "291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" + + "87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" + + "a1e00e39c757f064518953f55621f955986f63", + }, + { + key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785", + tag: "b431c9318ec2769fc8ee8f5fc3c079c3", + in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" + + "b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" + + "9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" + + "80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" + + "17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" + + "259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" + + "d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" + + "4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" + + "37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" + + "1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" + + "b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" + + "3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" + + "f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" + + "553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" + + "027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" + + "b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" + + "da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" + + "0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" + + "8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" + + "59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" + + "8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" + + "ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" + + "880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" + + "1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" + + "e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" + + "506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" + + "6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" + + "b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" + + "dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" + + "ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" + + "559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" + + "5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" + + "4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" + + "da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" + + "a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" + + "4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" + + "3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428", + }, + { + key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873", + tag: "907dba0f4849c7cf4570b5128b5f31d5", + in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" + + "887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" + + "eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" + + "bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" + + "2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" + + "d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" + + "17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" + + "2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" + + "9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" + + "507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" + + "40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" + + "d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" + + "4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" + + "78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" + + "b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" + + "887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" + + "83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" + + "32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" + + "9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" + + "0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" + + "46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" + + "5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" + + "7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" + + "e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" + + "8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" + + "490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" + + "6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" + + "933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" + + "45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" + + "885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" + + "1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" + + "2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" + + "23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" + + "6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" + + "2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" + + "a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" + + "e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" + + "8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" + + "942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" + + "b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" + + "1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" + + "43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" + + "eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6", + }, + { + key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88", + tag: "68eb7fc459ecc3be819485001ab438dc", + in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" + + "ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" + + "7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" + + "5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" + + "89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" + + "d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" + + "ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" + + "fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" + + "5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" + + "efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" + + "dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" + + "017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" + + "7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" + + "74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" + + "14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" + + "b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" + + "78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" + + "121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" + + "5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" + + "1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" + + "5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" + + "48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" + + "d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" + + "e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" + + "23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" + + "fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" + + "1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" + + "924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" + + "fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" + + "12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" + + "a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" + + "a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" + + "ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" + + "c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" + + "8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" + + "625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" + + "8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" + + "f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" + + "d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" + + "5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" + + "316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" + + "272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" + + "6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" + + "b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" + + "46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" + + "e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" + + "7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" + + "a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" + + "3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" + + "574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" + + "27c42e", + }, + { + key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238", + tag: "938b43b80cb3935e39b21dd8ba133cf8", + in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" + + "d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" + + "9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" + + "3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" + + "dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" + + "d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" + + "be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" + + "56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" + + "e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" + + "2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" + + "a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" + + "0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" + + "68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" + + "bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" + + "b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" + + "ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" + + "4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" + + "a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" + + "cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" + + "bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" + + "a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" + + "bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" + + "9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" + + "b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" + + "9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" + + "2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" + + "a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" + + "d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" + + "d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" + + "2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" + + "3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" + + "e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" + + "eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" + + "ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" + + "d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" + + "7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" + + "0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" + + "6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" + + "da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" + + "3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" + + "14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" + + "d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" + + "e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" + + "533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" + + "c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" + + "03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" + + "faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" + + "b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" + + "952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" + + "dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" + + "5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" + + "cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" + + "9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" + + "14d6e3da5c12fabe92bd639e253983fc91041091791643", + }, + { + key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e", + tag: "56b5f49be824c7a19b19faabf0787a87", + in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" + + "3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" + + "7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" + + "0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" + + "dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" + + "a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" + + "96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" + + "c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" + + "d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" + + "953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" + + "0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" + + "6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" + + "dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" + + "f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" + + "586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" + + "2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" + + "93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" + + "c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" + + "6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" + + "5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" + + "1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" + + "66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" + + "bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" + + "938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" + + "e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" + + "6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" + + "7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" + + "016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" + + "ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" + + "d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" + + "d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" + + "c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" + + "d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" + + "d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" + + "84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" + + "3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" + + "7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" + + "1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" + + "0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" + + "22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" + + "777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" + + "7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" + + "60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" + + "9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" + + "7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" + + "a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" + + "4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" + + "ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" + + "cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" + + "0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" + + "40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" + + "6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" + + "fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" + + "f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" + + "17554437d9642e2e", + }, + { + key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0", + tag: "72c9534aec8c1d883eef899f04e1c65e", + in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" + + "89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" + + "6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" + + "4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" + + "46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" + + "4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" + + "a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" + + "4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" + + "715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" + + "bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" + + "8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" + + "ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" + + "c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" + + "411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" + + "403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" + + "8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" + + "7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" + + "038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" + + "1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" + + "27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" + + "4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" + + "977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" + + "2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" + + "171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" + + "e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" + + "f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" + + "6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" + + "6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" + + "cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" + + "592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" + + "3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" + + "e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" + + "58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" + + "10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" + + "6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" + + "535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" + + "40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" + + "ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" + + "610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" + + "a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" + + "4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" + + "24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" + + "fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" + + "881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" + + "b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" + + "6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" + + "db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" + + "8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" + + "fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" + + "4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" + + "9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" + + "1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" + + "72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" + + "b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" + + "cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" + + "b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" + + "3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" + + "90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" + + "b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" + + "d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" + + "60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" + + "970a09d71061e6df751f100abfbf", + }, + { + key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1", + tag: "6b9782f2a09b59653aa448348a49291b", + in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" + + "f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" + + "a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" + + "bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" + + "d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" + + "b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" + + "f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" + + "ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" + + "fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" + + "0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" + + "a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" + + "0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" + + "656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" + + "9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" + + "94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" + + "728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" + + "cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" + + "f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" + + "41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" + + "ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" + + "6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" + + "1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" + + "a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" + + "eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" + + "c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" + + "c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" + + "614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" + + "f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" + + "33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" + + "1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" + + "30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" + + "4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" + + "dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" + + "5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" + + "259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" + + "f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" + + "1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" + + "244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" + + "80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" + + "7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" + + "3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" + + "520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" + + "7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" + + "3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" + + "070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" + + "9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" + + "04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" + + "faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" + + "898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" + + "0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" + + "45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" + + "99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" + + "f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" + + "3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" + + "2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" + + "eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" + + "7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" + + "56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" + + "2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" + + "64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" + + "6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" + + "c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" + + "81291a8290", + }, + { + key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1", + tag: "d9ab81fab28b3be96fa3331714e78c9a", + in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" + + "19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" + + "49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" + + "5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" + + "3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" + + "bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" + + "d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" + + "da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" + + "2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" + + "e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" + + "3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" + + "80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" + + "e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" + + "0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" + + "5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" + + "7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" + + "d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" + + "60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" + + "e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" + + "9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" + + "bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" + + "84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" + + "86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" + + "b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" + + "3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" + + "7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" + + "082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" + + "73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" + + "694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" + + "d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" + + "53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" + + "4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" + + "5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" + + "d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" + + "f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" + + "004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" + + "16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" + + "2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" + + "c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" + + "9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" + + "be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" + + "14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" + + "456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" + + "9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" + + "c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" + + "62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" + + "13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" + + "43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" + + "bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" + + "402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" + + "99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" + + "a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" + + "ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" + + "98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" + + "319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" + + "dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" + + "cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" + + "58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" + + "544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" + + "c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" + + "0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" + + "0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" + + "fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" + + "3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" + + "5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9", + }, + { + key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4", + tag: "41c32ced08a16bb35ac8c23868f58ac9", + in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" + + "ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" + + "6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" + + "e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" + + "4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" + + "0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" + + "01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" + + "74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" + + "8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" + + "6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" + + "ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" + + "3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" + + "a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" + + "afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" + + "169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" + + "b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" + + "0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" + + "4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" + + "3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" + + "bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" + + "f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" + + "5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" + + "1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" + + "f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" + + "8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" + + "b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" + + "93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" + + "5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" + + "40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" + + "74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" + + "c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" + + "7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" + + "cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" + + "405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" + + "ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" + + "0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" + + "50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" + + "ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" + + "9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" + + "430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" + + "4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" + + "c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" + + "f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" + + "f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" + + "9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" + + "18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" + + "4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" + + "4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" + + "48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" + + "d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" + + "d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" + + "a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" + + "11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" + + "5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" + + "ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" + + "24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" + + "1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" + + "5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" + + "873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" + + "1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" + + "2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" + + "ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" + + "60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" + + "9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" + + "90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" + + "db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" + + "4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" + + "407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" + + "7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" + + "0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" + + "640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" + + "59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" + + "6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" + + "9c7a9ba069deee", + }, + { + key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa", + tag: "3c95668130de728d24f7bca0c91588bc", + in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" + + "43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" + + "58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" + + "7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" + + "f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" + + "ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" + + "2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" + + "c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" + + "a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" + + "24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" + + "51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" + + "8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" + + "4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" + + "2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" + + "c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" + + "a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" + + "c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" + + "a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" + + "80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" + + "06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" + + "1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" + + "796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" + + "d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" + + "337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" + + "51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" + + "9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" + + "b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" + + "195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" + + "800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" + + "e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" + + "8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" + + "fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" + + "5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" + + "e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" + + "185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" + + "8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" + + "9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" + + "4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" + + "642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" + + "ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" + + "acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" + + "4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" + + "0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" + + "5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" + + "33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" + + "ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" + + "82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" + + "8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" + + "80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" + + "de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" + + "d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" + + "6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" + + "314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" + + "0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" + + "ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" + + "0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" + + "c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" + + "89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" + + "456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" + + "3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" + + "4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" + + "3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" + + "0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" + + "14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" + + "d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" + + "f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" + + "c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" + + "23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" + + "3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" + + "9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" + + "18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" + + "e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" + + "8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" + + "3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" + + "1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" + + "05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" + + "2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" + + "41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" + + "611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" + + "8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" + + "144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" + + "2ae937ecccdb6031d94cb3", + }, + { + key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b", + tag: "12dd5297cfcec53deae1dd5f9325d894", + in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" + + "388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" + + "3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" + + "b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" + + "458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" + + "2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" + + "9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" + + "a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" + + "4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" + + "442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" + + "662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" + + "045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" + + "bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" + + "ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" + + "053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" + + "070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" + + "b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" + + "9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" + + "00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" + + "b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" + + "e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" + + "2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" + + "a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" + + "bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" + + "f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" + + "8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" + + "9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" + + "854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" + + "b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" + + "d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" + + "2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" + + "46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" + + "e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" + + "de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" + + "4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" + + "c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" + + "0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" + + "55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" + + "4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" + + "5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" + + "83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" + + "745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" + + "785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" + + "d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" + + "7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" + + "1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" + + "507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" + + "0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" + + "98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" + + "1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" + + "e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" + + "c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" + + "6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" + + "6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" + + "b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" + + "a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" + + "bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" + + "657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" + + "92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" + + "b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" + + "85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" + + "150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" + + "bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" + + "ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" + + "c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" + + "a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" + + "894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" + + "6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" + + "8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" + + "7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" + + "b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" + + "e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" + + "e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" + + "822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" + + "890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" + + "6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" + + "70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" + + "45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" + + "09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" + + "e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" + + "9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" + + "0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" + + "755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" + + "06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" + + "f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" + + "a5", + }, + { + key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c", + tag: "a2c77b55cb0c076d8ea83cfe0e64f293", + in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" + + "16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" + + "e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" + + "33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" + + "c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" + + "460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" + + "70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" + + "9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" + + "178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" + + "4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" + + "f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" + + "97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" + + "7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" + + "031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" + + "bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" + + "65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" + + "98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" + + "dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" + + "2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" + + "16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" + + "2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" + + "9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" + + "2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" + + "209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" + + "8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" + + "e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" + + "b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" + + "021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" + + "9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" + + "dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" + + "29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" + + "375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" + + "f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" + + "555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" + + "da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" + + "cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" + + "1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" + + "8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" + + "69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" + + "b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" + + "e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" + + "89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" + + "45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" + + "80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" + + "98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" + + "14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" + + "4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" + + "b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" + + "16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" + + "8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" + + "39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" + + "b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" + + "251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" + + "b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" + + "11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" + + "0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" + + "481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" + + "0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" + + "3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" + + "edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" + + "9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" + + "22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" + + "8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" + + "51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" + + "ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" + + "dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" + + "a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" + + "72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" + + "6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" + + "70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" + + "065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" + + "40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" + + "307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" + + "38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" + + "a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" + + "621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" + + "731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" + + "b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" + + "77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" + + "c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" + + "c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" + + "a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" + + "1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" + + "7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" + + "cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" + + "8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" + + "5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" + + "71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" + + "1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" + + "527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" + + "bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" + + "c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" + + "a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f", + }, + { + key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080", + tag: "ec02f4953a9a63ab6f2bfc3501e4fab8", + in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" + + "887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" + + "1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" + + "049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" + + "f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" + + "4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" + + "fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" + + "813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" + + "c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" + + "520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" + + "ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" + + "cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" + + "65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" + + "686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" + + "7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" + + "4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" + + "6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" + + "717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" + + "c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" + + "7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" + + "782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" + + "1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" + + "12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" + + "4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" + + "d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" + + "bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" + + "61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" + + "068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" + + "c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" + + "0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" + + "d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" + + "0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" + + "cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" + + "072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" + + "3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" + + "b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" + + "2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" + + "4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" + + "50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" + + "fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" + + "da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" + + "4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" + + "c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" + + "a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" + + "d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" + + "db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" + + "1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" + + "77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" + + "7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" + + "4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" + + "3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" + + "001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" + + "6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" + + "13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" + + "44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" + + "264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" + + "cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" + + "f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" + + "df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" + + "e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" + + "cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" + + "9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" + + "31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" + + "13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" + + "14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" + + "329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" + + "903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" + + "cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" + + "a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" + + "5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" + + "f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" + + "4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" + + "64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" + + "74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" + + "5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" + + "85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" + + "73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" + + "7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" + + "f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" + + "4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" + + "584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" + + "f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" + + "c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" + + "0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" + + "90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" + + "b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" + + "3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" + + "4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" + + "bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" + + "20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" + + "f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" + + "318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" + + "4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" + + "ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" + + "7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" + + "0040194dfe66811542ddaa658094a9580d4e4b4e29", + }, + { + key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5", + tag: "429b2b39195a10357043c9601590a277", + in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" + + "c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" + + "c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" + + "6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" + + "40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" + + "d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" + + "300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" + + "33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" + + "dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" + + "d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" + + "b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" + + "30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" + + "a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" + + "eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" + + "c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" + + "04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" + + "8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" + + "f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" + + "cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" + + "2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" + + "0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" + + "f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" + + "bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" + + "6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" + + "003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" + + "31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" + + "7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" + + "a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" + + "29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" + + "bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" + + "dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" + + "b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" + + "91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" + + "eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" + + "2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" + + "d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" + + "1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" + + "3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" + + "3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" + + "ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" + + "ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" + + "ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" + + "89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" + + "fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" + + "7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" + + "f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" + + "ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" + + "be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" + + "6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" + + "de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" + + "2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" + + "cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" + + "0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" + + "77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" + + "020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" + + "4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" + + "ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" + + "650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" + + "3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" + + "aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" + + "ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" + + "54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" + + "396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" + + "6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" + + "575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" + + "b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" + + "79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" + + "6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" + + "5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" + + "ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" + + "e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" + + "d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" + + "55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" + + "f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" + + "aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" + + "2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" + + "7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" + + "d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" + + "5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" + + "e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" + + "74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" + + "5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" + + "865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" + + "1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" + + "b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" + + "d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" + + "7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" + + "753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" + + "01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" + + "f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" + + "b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" + + "4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" + + "0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" + + "925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" + + "dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" + + "f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b", + }, + { + key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe", + tag: "fbd3f884a3dc2a8be06ce03883282e1e", + in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" + + "dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" + + "57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" + + "be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" + + "a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" + + "bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" + + "f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" + + "f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" + + "d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" + + "cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" + + "b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" + + "4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" + + "88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" + + "7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" + + "a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" + + "d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" + + "fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" + + "84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" + + "b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" + + "286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" + + "951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" + + "9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" + + "41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" + + "3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" + + "6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" + + "58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" + + "c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" + + "7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" + + "a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" + + "dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" + + "79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" + + "7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" + + "a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" + + "460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" + + "6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" + + "32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" + + "b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" + + "51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" + + "8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" + + "e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" + + "86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" + + "69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" + + "ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" + + "e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" + + "b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" + + "17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" + + "3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" + + "21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" + + "5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" + + "f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" + + "bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" + + "002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" + + "676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" + + "7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" + + "212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" + + "be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" + + "755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" + + "016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" + + "d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" + + "a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" + + "662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" + + "fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" + + "ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" + + "89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" + + "6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" + + "576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" + + "6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" + + "c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" + + "689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" + + "623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" + + "910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" + + "38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" + + "a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" + + "80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" + + "d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" + + "2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" + + "16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" + + "e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" + + "ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" + + "bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" + + "d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" + + "6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" + + "f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" + + "4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" + + "ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" + + "abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" + + "10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" + + "ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" + + "696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" + + "4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" + + "ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" + + "cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" + + "0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" + + "2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" + + "b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" + + "7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" + + "f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" + + "bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" + + "8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" + + "d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" + + "653fe1969bbc2cb3685e64fd81d96d33", + }, + { + key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f", + tag: "d8a111a09db22b841fa28367ce35438b", + in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" + + "0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" + + "bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" + + "de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" + + "dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" + + "e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" + + "4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" + + "13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" + + "e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" + + "4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" + + "48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" + + "b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" + + "197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" + + "b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" + + "92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" + + "9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" + + "b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" + + "e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" + + "a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" + + "166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" + + "0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" + + "73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" + + "b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" + + "8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" + + "58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" + + "0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" + + "edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" + + "e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" + + "a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" + + "6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" + + "c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" + + "15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" + + "286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" + + "f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" + + "976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" + + "b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" + + "0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" + + "36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" + + "b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" + + "666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" + + "09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" + + "ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" + + "5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" + + "8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" + + "33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" + + "178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" + + "cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" + + "54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" + + "7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" + + "44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" + + "ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" + + "ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" + + "2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" + + "acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" + + "ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" + + "c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" + + "fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" + + "8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" + + "e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" + + "a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" + + "40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" + + "4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" + + "12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" + + "b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" + + "33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" + + "dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" + + "a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" + + "46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" + + "b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" + + "3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" + + "05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" + + "7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" + + "dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" + + "cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" + + "671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" + + "07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" + + "4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" + + "add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" + + "09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" + + "230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" + + "8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" + + "cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" + + "247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" + + "3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" + + "de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" + + "472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" + + "1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" + + "d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" + + "53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" + + "e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" + + "8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" + + "0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" + + "8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" + + "4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" + + "d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" + + "e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" + + "4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" + + "74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" + + "8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" + + "960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" + + "720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" + + "afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" + + "bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" + + "85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" + + "a510adcb05", + }, + { + key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1", + tag: "f01babc4901e957d0c2032a7279321e1", + in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" + + "dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" + + "665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" + + "7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" + + "ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" + + "f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" + + "b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" + + "41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" + + "dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" + + "971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" + + "cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" + + "6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" + + "2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" + + "a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" + + "367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" + + "dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" + + "c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" + + "181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" + + "5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" + + "aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" + + "2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" + + "d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" + + "30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" + + "236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" + + "1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" + + "b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" + + "baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" + + "fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" + + "67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" + + "219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" + + "58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" + + "bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" + + "4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" + + "e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" + + "c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" + + "976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" + + "5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" + + "1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" + + "1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" + + "d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" + + "a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" + + "719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" + + "dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" + + "ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" + + "e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" + + "465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" + + "bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" + + "927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" + + "d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" + + "909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" + + "fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" + + "9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" + + "d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" + + "a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" + + "4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" + + "09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" + + "306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" + + "eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" + + "dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" + + "acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" + + "4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" + + "88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" + + "73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" + + "91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" + + "977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" + + "6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" + + "0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" + + "ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" + + "2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" + + "e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" + + "c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" + + "3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" + + "d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" + + "9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" + + "a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" + + "97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" + + "bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" + + "2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" + + "c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" + + "d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" + + "fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" + + "dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" + + "ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" + + "1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" + + "a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" + + "da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" + + "834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" + + "4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" + + "762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" + + "dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" + + "cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" + + "3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" + + "9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" + + "2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" + + "4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" + + "6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" + + "61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" + + "c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" + + "99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" + + "543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" + + "aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" + + "83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" + + "fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" + + "7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" + + "fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" + + "ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" + + "edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" + + "e2", + }, + { + key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372", + tag: "81b1a6633f849ab0aa7baafa58a5d9b8", + in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" + + "3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" + + "20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" + + "02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" + + "df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" + + "10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" + + "c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" + + "240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" + + "f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" + + "495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" + + "f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" + + "d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" + + "bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" + + "923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" + + "74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" + + "9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" + + "12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" + + "245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" + + "5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" + + "21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" + + "16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" + + "5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" + + "2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" + + "6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" + + "dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" + + "d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" + + "634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" + + "4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" + + "908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" + + "b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" + + "bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" + + "90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" + + "a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" + + "618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" + + "dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" + + "4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" + + "88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" + + "4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" + + "cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" + + "d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" + + "09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" + + "7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" + + "1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" + + "8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" + + "86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" + + "3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" + + "61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" + + "aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" + + "a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" + + "a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" + + "72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" + + "1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" + + "72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" + + "dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" + + "cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" + + "788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" + + "2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" + + "29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" + + "d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" + + "1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" + + "e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" + + "1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" + + "e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" + + "08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" + + "aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" + + "4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" + + "8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" + + "0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" + + "04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" + + "d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" + + "f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" + + "fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" + + "7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" + + "a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" + + "ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" + + "fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" + + "7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" + + "faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" + + "e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" + + "a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" + + "d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" + + "09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" + + "a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" + + "3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" + + "9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" + + "7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" + + "b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" + + "2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" + + "ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" + + "09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" + + "eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" + + "b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" + + "0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" + + "1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" + + "8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" + + "c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" + + "08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" + + "1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" + + "aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" + + "1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" + + "f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" + + "7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" + + "04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" + + "84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" + + "db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" + + "b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" + + "9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" + + "97f8f3bc", + }, + { + key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a", + tag: "719dbe5a028d634398ce98e6702a164b", + in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" + + "cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" + + "82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" + + "0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" + + "78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" + + "db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" + + "b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" + + "cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" + + "4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" + + "dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" + + "453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" + + "f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" + + "24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" + + "fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" + + "74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" + + "08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" + + "4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" + + "1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" + + "fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" + + "7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" + + "34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" + + "7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" + + "37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" + + "37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" + + "bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" + + "ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" + + "a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" + + "0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" + + "1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" + + "ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" + + "f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" + + "83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" + + "72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" + + "5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" + + "4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" + + "0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" + + "ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" + + "1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" + + "9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" + + "a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" + + "794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" + + "565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" + + "ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" + + "f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" + + "b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" + + "839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" + + "2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" + + "d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" + + "c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" + + "280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" + + "d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" + + "ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" + + "6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" + + "a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" + + "59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" + + "9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" + + "a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" + + "ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" + + "be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" + + "532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" + + "726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" + + "54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" + + "77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" + + "a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" + + "c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" + + "dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" + + "bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" + + "c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" + + "5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" + + "0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" + + "86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" + + "e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" + + "da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" + + "c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" + + "04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" + + "6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" + + "c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" + + "ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" + + "4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" + + "fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" + + "9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" + + "0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" + + "311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" + + "8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" + + "3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" + + "d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" + + "3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" + + "0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" + + "9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" + + "c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" + + "c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" + + "6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" + + "f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" + + "de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" + + "73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" + + "edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" + + "380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" + + "42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" + + "4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" + + "c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" + + "2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" + + "de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" + + "721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" + + "6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" + + "bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" + + "ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" + + "194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" + + "00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" + + "eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" + + "31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" + + "3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" + + "732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" + + "43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" + + "d11e8f6f57d087fa72909785573008b1", + }, + { + key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03", + tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a", + in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" + + "89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" + + "9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" + + "2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" + + "dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" + + "239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" + + "61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" + + "89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" + + "6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" + + "7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" + + "562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" + + "3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" + + "15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" + + "8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" + + "e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" + + "9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" + + "03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" + + "add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" + + "dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" + + "00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" + + "ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" + + "3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" + + "c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" + + "3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" + + "ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" + + "fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" + + "4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" + + "ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" + + "5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" + + "abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" + + "ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" + + "463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" + + "66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" + + "7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" + + "1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" + + "f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" + + "540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" + + "69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" + + "841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" + + "522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" + + "1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" + + "a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" + + "270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" + + "d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" + + "1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" + + "aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" + + "f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" + + "d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" + + "40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" + + "5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" + + "13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" + + "15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" + + "aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" + + "5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" + + "b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" + + "128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" + + "8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" + + "4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" + + "4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" + + "777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" + + "f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" + + "386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" + + "5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" + + "1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" + + "4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" + + "9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" + + "3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" + + "ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" + + "5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" + + "ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" + + "ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" + + "98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" + + "549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" + + "30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" + + "3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" + + "7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" + + "d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" + + "36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" + + "9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" + + "4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" + + "a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" + + "038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" + + "df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" + + "f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" + + "60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" + + "fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" + + "865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" + + "4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" + + "da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" + + "7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" + + "bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" + + "baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" + + "2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" + + "35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" + + "eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" + + "3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" + + "776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" + + "25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" + + "790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" + + "203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" + + "ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" + + "ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" + + "d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" + + "cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" + + "b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" + + "59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" + + "e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" + + "a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" + + "4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" + + "99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" + + "c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" + + "ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" + + "264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" + + "77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" + + "50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" + + "48cc07016ec79808b180e0b258c564739185da754f2e", + }, + { + key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a", + tag: "42df9f9a59d6dc05c98fd9e9577f7176", + in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" + + "2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" + + "8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" + + "9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" + + "cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" + + "ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" + + "df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" + + "f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" + + "f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" + + "a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" + + "60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" + + "8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" + + "129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" + + "9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" + + "7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" + + "59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" + + "4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" + + "634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" + + "585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" + + "b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" + + "250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" + + "032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" + + "1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" + + "f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" + + "50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" + + "c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" + + "af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" + + "7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" + + "346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" + + "9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" + + "e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" + + "ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" + + "17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" + + "50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" + + "8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" + + "75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" + + "f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" + + "20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" + + "fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" + + "aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" + + "77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" + + "74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" + + "5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" + + "96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" + + "683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" + + "e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" + + "99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" + + "0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" + + "decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" + + "77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" + + "efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" + + "06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" + + "4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" + + "0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" + + "4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" + + "2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" + + "1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" + + "f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" + + "ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" + + "002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" + + "bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" + + "b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" + + "450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" + + "ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" + + "f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" + + "0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" + + "e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" + + "ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" + + "32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" + + "bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" + + "dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" + + "2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" + + "2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" + + "874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" + + "a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" + + "36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" + + "5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" + + "6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" + + "4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" + + "c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" + + "64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" + + "ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" + + "46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" + + "f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" + + "7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" + + "e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" + + "78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" + + "59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" + + "01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" + + "d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" + + "012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" + + "2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" + + "cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" + + "daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" + + "d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" + + "fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" + + "f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" + + "e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" + + "f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" + + "a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" + + "0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" + + "c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" + + "61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" + + "d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" + + "2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" + + "2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" + + "37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" + + "0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" + + "3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" + + "df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" + + "57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" + + "7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" + + "e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" + + "daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" + + "1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" + + "689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" + + "0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" + + "8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" + + "a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" + + "b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" + + "6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" + + "5cf93ce404be", + }, + { + key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2", + tag: "af608b71a353e63c64911558baa122f3", + in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" + + "cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" + + "fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" + + "3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" + + "261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" + + "fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" + + "a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" + + "5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" + + "7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" + + "b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" + + "b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" + + "aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" + + "1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" + + "d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" + + "5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" + + "c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" + + "77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" + + "9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" + + "b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" + + "2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" + + "9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" + + "e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" + + "51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" + + "9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" + + "473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" + + "6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" + + "9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" + + "ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" + + "084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" + + "88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" + + "f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" + + "340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" + + "cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" + + "0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" + + "4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" + + "8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" + + "6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" + + "46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" + + "226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" + + "6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" + + "bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" + + "fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" + + "0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" + + "7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" + + "838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" + + "11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" + + "af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" + + "a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" + + "afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" + + "1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" + + "b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" + + "7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" + + "3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" + + "078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" + + "f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" + + "1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" + + "963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" + + "91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" + + "407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" + + "bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" + + "403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" + + "7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" + + "f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" + + "1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" + + "37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" + + "57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" + + "2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" + + "e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" + + "fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" + + "e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" + + "ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" + + "a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" + + "bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" + + "9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" + + "2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" + + "2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" + + "6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" + + "d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" + + "b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" + + "5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" + + "3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" + + "36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" + + "fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" + + "4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" + + "c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" + + "5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" + + "91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" + + "79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" + + "3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" + + "06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" + + "de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" + + "b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" + + "9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" + + "37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" + + "88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" + + "a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" + + "fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" + + "ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" + + "3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" + + "52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" + + "86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" + + "793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" + + "832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" + + "5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" + + "5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" + + "a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" + + "91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" + + "813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" + + "6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" + + "90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" + + "03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" + + "3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" + + "dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" + + "6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" + + "a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" + + "f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" + + "2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" + + "a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" + + "1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" + + "2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" + + "734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" + + "046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" + + "df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" + + "6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" + + "da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" + + "42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" + + "bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" + + "4c3ba6ebf54bc7a1", + }, + { + key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a", + tag: "b0e4ad4a010afd6dd41ed82868cda555", + in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" + + "6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" + + "547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" + + "35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" + + "a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" + + "d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" + + "f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" + + "a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" + + "ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" + + "23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" + + "829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" + + "602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" + + "6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" + + "dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" + + "836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" + + "c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" + + "769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" + + "019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" + + "f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" + + "9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" + + "24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" + + "44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" + + "fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" + + "1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" + + "02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" + + "2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" + + "cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" + + "1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" + + "f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" + + "85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" + + "d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" + + "dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" + + "a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" + + "7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" + + "152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" + + "134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" + + "8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" + + "418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" + + "9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" + + "716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" + + "cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" + + "dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" + + "dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" + + "b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" + + "a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" + + "a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" + + "88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" + + "4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" + + "b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" + + "3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" + + "482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" + + "30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" + + "40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" + + "5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" + + "f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" + + "bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" + + "af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" + + "991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" + + "c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" + + "c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" + + "976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" + + "6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" + + "264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" + + "cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" + + "cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" + + "1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" + + "c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" + + "21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" + + "29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" + + "bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" + + "b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" + + "e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" + + "873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" + + "1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" + + "a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" + + "e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" + + "69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" + + "5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" + + "7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" + + "8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" + + "dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" + + "0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" + + "fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" + + "b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" + + "de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" + + "e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" + + "765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" + + "4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" + + "ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" + + "0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" + + "5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" + + "57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" + + "2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" + + "13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" + + "3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" + + "10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" + + "073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" + + "80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" + + "cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" + + "f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" + + "d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" + + "9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" + + "5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" + + "c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" + + "532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" + + "972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" + + "32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" + + "ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" + + "fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" + + "9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" + + "897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" + + "f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" + + "66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" + + "82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" + + "2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" + + "a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" + + "525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" + + "da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" + + "76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" + + "97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" + + "f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" + + "7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" + + "fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" + + "916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" + + "ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" + + "e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" + + "01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" + + "48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" + + "181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" + + "89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b", + }, + { + key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418", + tag: "e1122e7c8e6965b90addbd46d8a548d6", + in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" + + "58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" + + "54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" + + "967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" + + "a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" + + "96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" + + "d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" + + "905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" + + "365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" + + "b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" + + "2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" + + "d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" + + "256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" + + "eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" + + "10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" + + "77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" + + "3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" + + "4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" + + "81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" + + "67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" + + "bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" + + "d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" + + "5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" + + "5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" + + "597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" + + "ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" + + "c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" + + "8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" + + "74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" + + "133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" + + "155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" + + "5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" + + "8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" + + "e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" + + "84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" + + "77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" + + "6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" + + "2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" + + "38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" + + "87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" + + "8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" + + "141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" + + "fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" + + "1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" + + "122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" + + "78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" + + "a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" + + "ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" + + "2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" + + "6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" + + "f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" + + "c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" + + "c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" + + "8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" + + "9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" + + "9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" + + "286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" + + "e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" + + "e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" + + "e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" + + "6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" + + "33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" + + "58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" + + "84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" + + "7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" + + "b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" + + "5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" + + "90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" + + "5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" + + "8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" + + "6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" + + "d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" + + "57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" + + "e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" + + "a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" + + "28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" + + "0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" + + "bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" + + "6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" + + "d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" + + "44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" + + "0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" + + "9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" + + "1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" + + "267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" + + "352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" + + "212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" + + "2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" + + "50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" + + "eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" + + "9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" + + "0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" + + "5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" + + "c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" + + "9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" + + "998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" + + "e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" + + "beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" + + "b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" + + "4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" + + "4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" + + "7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" + + "15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" + + "fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" + + "a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" + + "238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" + + "0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" + + "090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" + + "d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" + + "7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" + + "ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" + + "587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" + + "6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" + + "c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" + + "4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" + + "7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" + + "41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" + + "e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" + + "d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" + + "be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" + + "ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" + + "22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" + + "092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" + + "f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" + + "5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" + + "d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" + + "d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" + + "71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" + + "d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" + + "eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" + + "f2c5b0dc5de9f5e55a97791507bc6373db26", + }, +} diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go index 5df1b25..a1fbffd 100644 --- a/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go @@ -50,15 +50,23 @@ func TestVectors(t *testing.T) { } } -func TestMillionA(t *testing.T) { +func millionA() string { md := New() for i := 0; i < 100000; i++ { io.WriteString(md, "aaaaaaaaaa") } - out := "52783243c1697bdbe16d37f97f68f08325dc1528" - s := fmt.Sprintf("%x", md.Sum(nil)) - if s != out { + return fmt.Sprintf("%x", md.Sum(nil)) +} + +func TestMillionA(t *testing.T) { + const out = "52783243c1697bdbe16d37f97f68f08325dc1528" + if s := millionA(); s != out { t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) } - md.Reset() +} + +func BenchmarkMillionA(b *testing.B) { + for i := 0; i < b.N; i++ { + millionA() + } } diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go index 7bc8e6c..e0edc02 100644 --- a/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go @@ -8,6 +8,10 @@ package ripemd160 +import ( + "math/bits" +) + // work buffer indices and roll amounts for one line var _n = [80]uint{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -59,16 +63,16 @@ func _Block(md *digest, p []byte) int { i := 0 for i < 16 { alpha = a + (b ^ c ^ d) + x[_n[i]] - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 + s := int(_r[i]) + alpha = bits.RotateLeft32(alpha, s) + e + beta = bits.RotateLeft32(c, 10) a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 + s = int(r_[i]) + alpha = bits.RotateLeft32(alpha, s) + ee + beta = bits.RotateLeft32(cc, 10) aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ @@ -77,16 +81,16 @@ func _Block(md *digest, p []byte) int { // round 2 for i < 32 { alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 + s := int(_r[i]) + alpha = bits.RotateLeft32(alpha, s) + e + beta = bits.RotateLeft32(c, 10) a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 + s = int(r_[i]) + alpha = bits.RotateLeft32(alpha, s) + ee + beta = bits.RotateLeft32(cc, 10) aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ @@ -95,16 +99,16 @@ func _Block(md *digest, p []byte) int { // round 3 for i < 48 { alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 + s := int(_r[i]) + alpha = bits.RotateLeft32(alpha, s) + e + beta = bits.RotateLeft32(c, 10) a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 + s = int(r_[i]) + alpha = bits.RotateLeft32(alpha, s) + ee + beta = bits.RotateLeft32(cc, 10) aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ @@ -113,16 +117,16 @@ func _Block(md *digest, p []byte) int { // round 4 for i < 64 { alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 + s := int(_r[i]) + alpha = bits.RotateLeft32(alpha, s) + e + beta = bits.RotateLeft32(c, 10) a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 + s = int(r_[i]) + alpha = bits.RotateLeft32(alpha, s) + ee + beta = bits.RotateLeft32(cc, 10) aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ @@ -131,16 +135,16 @@ func _Block(md *digest, p []byte) int { // round 5 for i < 80 { alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 + s := int(_r[i]) + alpha = bits.RotateLeft32(alpha, s) + e + beta = bits.RotateLeft32(c, 10) a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 + s = int(r_[i]) + alpha = bits.RotateLeft32(alpha, s) + ee + beta = bits.RotateLeft32(cc, 10) aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa20.go index 0ee6248..6f9bb10 100644 --- a/vendor/golang.org/x/crypto/salsa20/salsa20.go +++ b/vendor/golang.org/x/crypto/salsa20/salsa20.go @@ -24,6 +24,7 @@ package salsa20 // import "golang.org/x/crypto/salsa20" // TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. import ( + "golang.org/x/crypto/internal/subtle" "golang.org/x/crypto/salsa20/salsa" ) @@ -32,7 +33,10 @@ import ( // be either 8 or 24 bytes long. func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { if len(out) < len(in) { - in = in[:len(out)] + panic("salsa20: output smaller than input") + } + if subtle.InexactOverlap(out[:len(in)], in) { + panic("salsa20: invalid buffer overlap") } var subNonce [16]byte diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go index ff28aae..9b25b5a 100644 --- a/vendor/golang.org/x/crypto/scrypt/scrypt.go +++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go @@ -218,7 +218,7 @@ func smix(b []byte, r, N int, v, xy []uint32) { // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) +// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) // // The recommended parameters for interactive logins as of 2017 are N=32768, r=8 // and p=1. The parameters N, r, and p should be increased as memory latency and diff --git a/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go index 2b51cf4..4fb38c0 100644 --- a/vendor/golang.org/x/crypto/sha3/hashes.go +++ b/vendor/golang.org/x/crypto/sha3/hashes.go @@ -15,22 +15,48 @@ import ( // New224 creates a new SHA3-224 hash. // Its generic security strength is 224 bits against preimage attacks, // and 112 bits against collision attacks. -func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } +func New224() hash.Hash { + if h := new224Asm(); h != nil { + return h + } + return &state{rate: 144, outputLen: 28, dsbyte: 0x06} +} // New256 creates a new SHA3-256 hash. // Its generic security strength is 256 bits against preimage attacks, // and 128 bits against collision attacks. -func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } +func New256() hash.Hash { + if h := new256Asm(); h != nil { + return h + } + return &state{rate: 136, outputLen: 32, dsbyte: 0x06} +} // New384 creates a new SHA3-384 hash. // Its generic security strength is 384 bits against preimage attacks, // and 192 bits against collision attacks. -func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } +func New384() hash.Hash { + if h := new384Asm(); h != nil { + return h + } + return &state{rate: 104, outputLen: 48, dsbyte: 0x06} +} // New512 creates a new SHA3-512 hash. // Its generic security strength is 512 bits against preimage attacks, // and 256 bits against collision attacks. -func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } +func New512() hash.Hash { + if h := new512Asm(); h != nil { + return h + } + return &state{rate: 72, outputLen: 64, dsbyte: 0x06} +} + +// NewLegacyKeccak256 creates a new Keccak-256 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New256 instead. +func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } // Sum224 returns the SHA3-224 digest of the data. func Sum224(data []byte) (digest [28]byte) { diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go new file mode 100644 index 0000000..c4ff3f6 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -0,0 +1,27 @@ +// Copyright 2017 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. + +//+build gccgo appengine !s390x + +package sha3 + +import ( + "hash" +) + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { return nil } + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { return nil } + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { return nil } + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { return nil } diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go new file mode 100644 index 0000000..f1fb79c --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -0,0 +1,289 @@ +// Copyright 2017 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. + +//+build !gccgo,!appengine + +package sha3 + +// This file contains code for using the 'compute intermediate +// message digest' (KIMD) and 'compute last message digest' (KLMD) +// instructions to compute SHA-3 and SHAKE hashes on IBM Z. + +import ( + "hash" +) + +// codes represent 7-bit KIMD/KLMD function codes as defined in +// the Principles of Operation. +type code uint64 + +const ( + // function codes for KIMD/KLMD + sha3_224 code = 32 + sha3_256 = 33 + sha3_384 = 34 + sha3_512 = 35 + shake_128 = 36 + shake_256 = 37 + nopad = 0x100 +) + +// hasMSA6 reports whether the machine supports the SHA-3 and SHAKE function +// codes, as defined in message-security-assist extension 6. +func hasMSA6() bool + +// hasAsm caches the result of hasMSA6 (which might be expensive to call). +var hasAsm = hasMSA6() + +// kimd is a wrapper for the 'compute intermediate message digest' instruction. +// src must be a multiple of the rate for the given function code. +//go:noescape +func kimd(function code, chain *[200]byte, src []byte) + +// klmd is a wrapper for the 'compute last message digest' instruction. +// src padding is handled by the instruction. +//go:noescape +func klmd(function code, chain *[200]byte, dst, src []byte) + +type asmState struct { + a [200]byte // 1600 bit state + buf []byte // care must be taken to ensure cap(buf) is a multiple of rate + rate int // equivalent to block size + storage [3072]byte // underlying storage for buf + outputLen int // output length if fixed, 0 if not + function code // KIMD/KLMD function code + state spongeDirection // whether the sponge is absorbing or squeezing +} + +func newAsmState(function code) *asmState { + var s asmState + s.function = function + switch function { + case sha3_224: + s.rate = 144 + s.outputLen = 28 + case sha3_256: + s.rate = 136 + s.outputLen = 32 + case sha3_384: + s.rate = 104 + s.outputLen = 48 + case sha3_512: + s.rate = 72 + s.outputLen = 64 + case shake_128: + s.rate = 168 + case shake_256: + s.rate = 136 + default: + panic("sha3: unrecognized function code") + } + + // limit s.buf size to a multiple of s.rate + s.resetBuf() + return &s +} + +func (s *asmState) clone() *asmState { + c := *s + c.buf = c.storage[:len(s.buf):cap(s.buf)] + return &c +} + +// copyIntoBuf copies b into buf. It will panic if there is not enough space to +// store all of b. +func (s *asmState) copyIntoBuf(b []byte) { + bufLen := len(s.buf) + s.buf = s.buf[:len(s.buf)+len(b)] + copy(s.buf[bufLen:], b) +} + +// resetBuf points buf at storage, sets the length to 0 and sets cap to be a +// multiple of the rate. +func (s *asmState) resetBuf() { + max := (cap(s.storage) / s.rate) * s.rate + s.buf = s.storage[:0:max] +} + +// Write (via the embedded io.Writer interface) adds more data to the running hash. +// It never returns an error. +func (s *asmState) Write(b []byte) (int, error) { + if s.state != spongeAbsorbing { + panic("sha3: write to sponge after read") + } + length := len(b) + for len(b) > 0 { + if len(s.buf) == 0 && len(b) >= cap(s.buf) { + // Hash the data directly and push any remaining bytes + // into the buffer. + remainder := len(s.buf) % s.rate + kimd(s.function, &s.a, b[:len(b)-remainder]) + if remainder != 0 { + s.copyIntoBuf(b[len(b)-remainder:]) + } + return length, nil + } + + if len(s.buf) == cap(s.buf) { + // flush the buffer + kimd(s.function, &s.a, s.buf) + s.buf = s.buf[:0] + } + + // copy as much as we can into the buffer + n := len(b) + if len(b) > cap(s.buf)-len(s.buf) { + n = cap(s.buf) - len(s.buf) + } + s.copyIntoBuf(b[:n]) + b = b[n:] + } + return length, nil +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (s *asmState) Read(out []byte) (n int, err error) { + n = len(out) + + // need to pad if we were absorbing + if s.state == spongeAbsorbing { + s.state = spongeSqueezing + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 + s.buf = s.buf[:0] + return + } + + // write hash into buffer + max := cap(s.buf) + if max > len(out) { + max = (len(out)/s.rate)*s.rate + s.rate + } + klmd(s.function, &s.a, s.buf[:max], s.buf) + s.buf = s.buf[:max] + } + + for len(out) > 0 { + // flush the buffer + if len(s.buf) != 0 { + c := copy(out, s.buf) + out = out[c:] + s.buf = s.buf[c:] + continue + } + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function|nopad, &s.a, out, nil) + return + } + + // write hash into buffer + s.resetBuf() + if cap(s.buf) > len(out) { + s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] + } + klmd(s.function|nopad, &s.a, s.buf, nil) + } + return +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (s *asmState) Sum(b []byte) []byte { + if s.outputLen == 0 { + panic("sha3: cannot call Sum on SHAKE functions") + } + + // Copy the state to preserve the original. + a := s.a + + // Hash the buffer. Note that we don't clear it because we + // aren't updating the state. + klmd(s.function, &a, nil, s.buf) + return append(b, a[:s.outputLen]...) +} + +// Reset resets the Hash to its initial state. +func (s *asmState) Reset() { + for i := range s.a { + s.a[i] = 0 + } + s.resetBuf() + s.state = spongeAbsorbing +} + +// Size returns the number of bytes Sum will return. +func (s *asmState) Size() int { + return s.outputLen +} + +// BlockSize returns the hash's underlying block size. +// The Write method must be able to accept any amount +// of data, but it may operate more efficiently if all writes +// are a multiple of the block size. +func (s *asmState) BlockSize() int { + return s.rate +} + +// Clone returns a copy of the ShakeHash in its current state. +func (s *asmState) Clone() ShakeHash { + return s.clone() +} + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_224) + } + return nil +} + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_256) + } + return nil +} + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_384) + } + return nil +} + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_512) + } + return nil +} + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + if hasAsm { + return newAsmState(shake_128) + } + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + if hasAsm { + return newAsmState(shake_256) + } + return nil +} diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s new file mode 100644 index 0000000..20978fc --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -0,0 +1,49 @@ +// Copyright 2017 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. + +//+build !gccgo,!appengine + +#include "textflag.h" + +TEXT ·hasMSA6(SB), NOSPLIT, $16-1 + MOVD $0, R0 // KIMD-Query function code + MOVD $tmp-16(SP), R1 // parameter block + XC $16, (R1), (R1) // clear the parameter block + WORD $0xB93E0002 // KIMD --, -- + WORD $0x91FC1004 // TM 4(R1), 0xFC (test bits [32-37]) + BVS yes + +no: + MOVB $0, ret+0(FP) + RET + +yes: + MOVB $1, ret+0(FP) + RET + +// func kimd(function code, params *[200]byte, src []byte) +TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 + MOVD function+0(FP), R0 + MOVD params+8(FP), R1 + LMG src+16(FP), R2, R3 // R2=base, R3=len + +continue: + WORD $0xB93E0002 // KIMD --, R2 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET + +// func klmd(function code, params *[200]byte, dst, src []byte) +TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 + // TODO: SHAKE support + MOVD function+0(FP), R0 + MOVD params+8(FP), R1 + LMG dst+16(FP), R2, R3 // R2=base, R3=len + LMG src+40(FP), R4, R5 // R4=base, R5=len + +continue: + WORD $0xB93F0024 // KLMD R2, R4 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET diff --git a/vendor/golang.org/x/crypto/sha3/sha3_test.go b/vendor/golang.org/x/crypto/sha3/sha3_test.go index 2c8719b..c1f6ca3 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_test.go +++ b/vendor/golang.org/x/crypto/sha3/sha3_test.go @@ -36,15 +36,16 @@ func newHashShake256() hash.Hash { } // testDigests contains functions returning hash.Hash instances -// with output-length equal to the KAT length for both SHA-3 and -// SHAKE instances. +// with output-length equal to the KAT length for SHA-3, Keccak +// and SHAKE instances. var testDigests = map[string]func() hash.Hash{ - "SHA3-224": New224, - "SHA3-256": New256, - "SHA3-384": New384, - "SHA3-512": New512, - "SHAKE128": newHashShake128, - "SHAKE256": newHashShake256, + "SHA3-224": New224, + "SHA3-256": New256, + "SHA3-384": New384, + "SHA3-512": New512, + "Keccak-256": NewLegacyKeccak256, + "SHAKE128": newHashShake128, + "SHAKE256": newHashShake256, } // testShakes contains functions that return ShakeHash instances for @@ -124,9 +125,34 @@ func TestKeccakKats(t *testing.T) { }) } +// TestKeccak does a basic test of the non-standardized Keccak hash functions. +func TestKeccak(t *testing.T) { + tests := []struct { + fn func() hash.Hash + data []byte + want string + }{ + { + NewLegacyKeccak256, + []byte("abc"), + "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", + }, + } + + for _, u := range tests { + h := u.fn() + h.Write(u.data) + got := h.Sum(nil) + want := decodeHex(u.want) + if !bytes.Equal(got, want) { + t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want) + } + } +} + // TestUnalignedWrite tests that writing data in an arbitrary pattern with // small input buffers. -func testUnalignedWrite(t *testing.T) { +func TestUnalignedWrite(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { buf := sequentialBytes(0x10000) for alg, df := range testDigests { diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go index 841f986..97c9b06 100644 --- a/vendor/golang.org/x/crypto/sha3/shake.go +++ b/vendor/golang.org/x/crypto/sha3/shake.go @@ -38,12 +38,22 @@ func (d *state) Clone() ShakeHash { // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. // Its generic security strength is 128 bits against all attacks if at // least 32 bytes of its output are used. -func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } +func NewShake128() ShakeHash { + if h := newShake128Asm(); h != nil { + return h + } + return &state{rate: 168, dsbyte: 0x1f} +} -// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. +// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. // Its generic security strength is 256 bits against all attacks if // at least 64 bytes of its output are used. -func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } +func NewShake256() ShakeHash { + if h := newShake256Asm(); h != nil { + return h + } + return &state{rate: 136, dsbyte: 0x1f} +} // ShakeSum128 writes an arbitrary-length digest of data into hash. func ShakeSum128(hash, data []byte) { diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go new file mode 100644 index 0000000..73d0c90 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +//+build gccgo appengine !s390x + +package sha3 + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go index acb5ad8..b1808dd 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/client.go +++ b/vendor/golang.org/x/crypto/ssh/agent/client.go @@ -8,7 +8,7 @@ // ssh-agent process using the sample server. // // References: -// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD +// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 package agent // import "golang.org/x/crypto/ssh/agent" import ( diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go index a6ba06a..1a51632 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/keyring.go +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -102,7 +102,7 @@ func (r *keyring) Unlock(passphrase []byte) error { if !r.locked { return errors.New("agent: not locked") } - if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { + if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { return fmt.Errorf("agent: incorrect passphrase") } diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go index cfc8ead..42106f3 100644 --- a/vendor/golang.org/x/crypto/ssh/certs.go +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -44,7 +44,9 @@ type Signature struct { const CertTimeInfinity = 1<<64 - 1 // An Certificate represents an OpenSSH certificate as defined in -// [PROTOCOL.certkeys]?rev=1.8. +// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the +// PublicKey interface, so it can be unmarshaled using +// ParsePublicKey. type Certificate struct { Nonce []byte Key PublicKey diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go index 9944139..67b0126 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher.go +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -16,6 +16,7 @@ import ( "hash" "io" "io/ioutil" + "math/bits" "golang.org/x/crypto/internal/chacha20" "golang.org/x/crypto/poly1305" @@ -56,78 +57,78 @@ func newRC4(key, iv []byte) (cipher.Stream, error) { return rc4.NewCipher(key) } -type streamCipherMode struct { - keySize int - ivSize int - skip int - createFunc func(key, iv []byte) (cipher.Stream, error) +type cipherMode struct { + keySize int + ivSize int + create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) } -func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { - if len(key) < c.keySize { - panic("ssh: key length too small for cipher") - } - if len(iv) < c.ivSize { - panic("ssh: iv too small for cipher") - } - - stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) - if err != nil { - return nil, err - } - - var streamDump []byte - if c.skip > 0 { - streamDump = make([]byte, 512) - } - - for remainingToDump := c.skip; remainingToDump > 0; { - dumpThisTime := remainingToDump - if dumpThisTime > len(streamDump) { - dumpThisTime = len(streamDump) +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + stream, err := createFunc(key, iv) + if err != nil { + return nil, err } - stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) - remainingToDump -= dumpThisTime - } - return stream, nil + var streamDump []byte + if skip > 0 { + streamDump = make([]byte, 512) + } + + for remainingToDump := skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + mac := macModes[algs.MAC].new(macKey) + return &streamPacketCipher{ + mac: mac, + etm: macModes[algs.MAC].etm, + macResult: make([]byte, mac.Size()), + cipher: stream, + }, nil + } } // cipherModes documents properties of supported ciphers. Ciphers not included // are not supported and will not be negotiated, even if explicitly requested in // ClientConfig.Crypto.Ciphers. -var cipherModes = map[string]*streamCipherMode{ +var cipherModes = map[string]*cipherMode{ // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms // are defined in the order specified in the RFC. - "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, - "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, - "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, + "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. // They are defined in the order specified in the RFC. - "arcfour128": {16, 0, 1536, newRC4}, - "arcfour256": {32, 0, 1536, newRC4}, + "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, + "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and // RC4) has problems with weak keys, and should be used with caution." // RFC4345 introduces improved versions of Arcfour. - "arcfour": {16, 0, 0, newRC4}, + "arcfour": {16, 0, streamCipherMode(0, newRC4)}, - // AEAD ciphers are special cased. If we add any more non-stream - // ciphers, we should create a cleaner way to do this. - gcmCipherID: {16, 12, 0, nil}, - chacha20Poly1305ID: {64, 0, 0, nil}, + // AEAD ciphers + gcmCipherID: {16, 12, newGCMCipher}, + chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, // CBC mode is insecure and so is not included in the default config. // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely // needed, it's possible to specify a custom Config to enable it. // You should expect that an active attacker can recover plaintext if // you do. - aes128cbcID: {16, aes.BlockSize, 0, nil}, + aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, - // 3des-cbc is insecure and is disabled by default. - tripledescbcID: {24, des.BlockSize, 0, nil}, + // 3des-cbc is insecure and is not included in the default + // config. + tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, } // prefixLen is the length of the packet prefix that contains the packet length @@ -307,7 +308,7 @@ type gcmCipher struct { buf []byte } -func newGCMCipher(iv, key []byte) (packetCipher, error) { +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err @@ -425,7 +426,7 @@ type cbcCipher struct { oracleCamouflage uint32 } -func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { cbc := &cbcCipher{ mac: macModes[algs.MAC].new(macKey), decrypter: cipher.NewCBCDecrypter(c, iv), @@ -439,13 +440,13 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith return cbc, nil } -func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } - cbc, err := newCBCCipher(c, iv, key, macKey, algs) + cbc, err := newCBCCipher(c, key, iv, macKey, algs) if err != nil { return nil, err } @@ -453,13 +454,13 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi return cbc, nil } -func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { c, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } - cbc, err := newCBCCipher(c, iv, key, macKey, algs) + cbc, err := newCBCCipher(c, key, iv, macKey, algs) if err != nil { return nil, err } @@ -641,42 +642,43 @@ const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" // the methods here also implement padding, which RFC4253 Section 6 // also requires of stream ciphers. type chacha20Poly1305Cipher struct { - lengthKey [32]byte - contentKey [32]byte + lengthKey [8]uint32 + contentKey [8]uint32 buf []byte } -func newChaCha20Cipher(key []byte) (packetCipher, error) { +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { if len(key) != 64 { - panic("key length") + panic(len(key)) } c := &chacha20Poly1305Cipher{ buf: make([]byte, 256), } - copy(c.contentKey[:], key[:32]) - copy(c.lengthKey[:], key[32:]) + for i := range c.contentKey { + c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4]) + } + for i := range c.lengthKey { + c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4]) + } return c, nil } -// The Poly1305 key is obtained by encrypting 32 0-bytes. -var chacha20PolyKeyInput [32]byte - func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { - var counter [16]byte - binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) - + nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} + s := chacha20.New(c.contentKey, nonce) var polyKey [32]byte - chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.Advance() // skip next 32 bytes encryptedLength := c.buf[:4] - if _, err := r.Read(encryptedLength); err != nil { + if _, err := io.ReadFull(r, encryptedLength); err != nil { return nil, err } var lenBytes [4]byte - chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey) + chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength) length := binary.BigEndian.Uint32(lenBytes[:]) if length > maxPacket { @@ -692,21 +694,18 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, c.buf = c.buf[:packetEnd] } - if _, err := r.Read(c.buf[4:packetEnd]); err != nil { + if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { return nil, err } var mac [poly1305.TagSize]byte copy(mac[:], c.buf[contentEnd:packetEnd]) - if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { return nil, errors.New("ssh: MAC failure") } - counter[0] = 1 - plain := c.buf[4:contentEnd] - chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey) + s.XORKeyStream(plain, plain) padding := plain[0] if padding < 4 { @@ -720,15 +719,16 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, } plain = plain[1 : len(plain)-int(padding)] + return plain, nil } func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { - var counter [16]byte - binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) - + nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} + s := chacha20.New(c.contentKey, nonce) var polyKey [32]byte - chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.Advance() // skip next 32 bytes // There is no blocksize, so fall back to multiple of 8 byte // padding, as described in RFC 4253, Sec 6. @@ -748,7 +748,7 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io } binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) - chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey) + chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4]) c.buf[4] = byte(padding) copy(c.buf[5:], payload) packetEnd := 5 + len(payload) + padding @@ -756,8 +756,7 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io return err } - counter[0] = 1 - chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey) + s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) var mac [poly1305.TagSize]byte poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go index 6a35d87..a52d6e4 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher_test.go +++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go @@ -7,7 +7,6 @@ package ssh import ( "bytes" "crypto" - "crypto/aes" "crypto/rand" "testing" ) @@ -15,7 +14,12 @@ import ( func TestDefaultCiphersExist(t *testing.T) { for _, cipherAlgo := range supportedCiphers { if _, ok := cipherModes[cipherAlgo]; !ok { - t.Errorf("default cipher %q is unknown", cipherAlgo) + t.Errorf("supported cipher %q is unknown", cipherAlgo) + } + } + for _, cipherAlgo := range preferredCiphers { + if _, ok := cipherModes[cipherAlgo]; !ok { + t.Errorf("preferred cipher %q is unknown", cipherAlgo) } } } @@ -67,9 +71,6 @@ func testPacketCipher(t *testing.T, cipher, mac string) { } func TestCBCOracleCounterMeasure(t *testing.T) { - cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} - defer delete(cipherModes, aes128cbcID) - kr := &kexResult{Hash: crypto.SHA1} algs := directionAlgorithms{ Cipher: aes128cbcID, diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go index 6fd1994..ae6ca77 100644 --- a/vendor/golang.org/x/crypto/ssh/client.go +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -19,6 +19,8 @@ import ( type Client struct { Conn + handleForwardsOnce sync.Once // guards calling (*Client).handleForwards + forwards forwardList // forwarded tcpip connections from the remote side mu sync.Mutex channelHandlers map[string]chan NewChannel @@ -60,8 +62,6 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { conn.Wait() conn.forwards.closeAll() }() - go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) - go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com")) return conn } diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go index a1252cb..5f44b77 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -11,6 +11,14 @@ import ( "io" ) +type authResult int + +const ( + authFailure authResult = iota + authPartialSuccess + authSuccess +) + // clientAuthenticate authenticates with the remote server. See RFC 4252. func (c *connection) clientAuthenticate(config *ClientConfig) error { // initiate user auth session @@ -37,11 +45,12 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { if err != nil { return err } - if ok { + if ok == authSuccess { // success return nil + } else if ok == authFailure { + tried[auth.method()] = true } - tried[auth.method()] = true if methods == nil { methods = lastMethods } @@ -82,7 +91,7 @@ type AuthMethod interface { // If authentication is not successful, a []string of alternative // method names is returned. If the slice is nil, it will be ignored // and the previous set of possible methods will be reused. - auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error) + auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error) // method returns the RFC 4252 method name. method() string @@ -91,13 +100,13 @@ type AuthMethod interface { // "none" authentication, RFC 4252 section 5.2. type noneAuth int -func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { if err := c.writePacket(Marshal(&userAuthRequestMsg{ User: user, Service: serviceSSH, Method: "none", })); err != nil { - return false, nil, err + return authFailure, nil, err } return handleAuthResponse(c) @@ -111,7 +120,7 @@ func (n *noneAuth) method() string { // a function call, e.g. by prompting the user. type passwordCallback func() (password string, err error) -func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { type passwordAuthMsg struct { User string `sshtype:"50"` Service string @@ -125,7 +134,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand // The program may only find out that the user doesn't have a password // when prompting. if err != nil { - return false, nil, err + return authFailure, nil, err } if err := c.writePacket(Marshal(&passwordAuthMsg{ @@ -135,7 +144,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand Reply: false, Password: pw, })); err != nil { - return false, nil, err + return authFailure, nil, err } return handleAuthResponse(c) @@ -178,7 +187,7 @@ func (cb publicKeyCallback) method() string { return "publickey" } -func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { // Authentication is performed by sending an enquiry to test if a key is // acceptable to the remote. If the key is acceptable, the client will // attempt to authenticate with the valid key. If not the client will repeat @@ -186,13 +195,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand signers, err := cb() if err != nil { - return false, nil, err + return authFailure, nil, err } var methods []string for _, signer := range signers { ok, err := validateKey(signer.PublicKey(), user, c) if err != nil { - return false, nil, err + return authFailure, nil, err } if !ok { continue @@ -206,7 +215,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand Method: cb.method(), }, []byte(pub.Type()), pubKey)) if err != nil { - return false, nil, err + return authFailure, nil, err } // manually wrap the serialized signature in a string @@ -224,24 +233,24 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand } p := Marshal(&msg) if err := c.writePacket(p); err != nil { - return false, nil, err + return authFailure, nil, err } - var success bool + var success authResult success, methods, err = handleAuthResponse(c) if err != nil { - return false, nil, err + return authFailure, nil, err } // If authentication succeeds or the list of available methods does not // contain the "publickey" method, do not attempt to authenticate with any // other keys. According to RFC 4252 Section 7, the latter can occur when // additional authentication methods are required. - if success || !containsMethod(methods, cb.method()) { + if success == authSuccess || !containsMethod(methods, cb.method()) { return success, methods, err } } - return false, methods, nil + return authFailure, methods, nil } func containsMethod(methods []string, method string) bool { @@ -318,28 +327,31 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet // handleAuthResponse returns whether the preceding authentication request succeeded // along with a list of remaining authentication methods to try next and // an error if an unexpected response was received. -func handleAuthResponse(c packetConn) (bool, []string, error) { +func handleAuthResponse(c packetConn) (authResult, []string, error) { for { packet, err := c.readPacket() if err != nil { - return false, nil, err + return authFailure, nil, err } switch packet[0] { case msgUserAuthBanner: if err := handleBannerResponse(c, packet); err != nil { - return false, nil, err + return authFailure, nil, err } case msgUserAuthFailure: var msg userAuthFailureMsg if err := Unmarshal(packet, &msg); err != nil { - return false, nil, err + return authFailure, nil, err } - return false, msg.Methods, nil + if msg.PartialSuccess { + return authPartialSuccess, msg.Methods, nil + } + return authFailure, msg.Methods, nil case msgUserAuthSuccess: - return true, nil, nil + return authSuccess, nil, nil default: - return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) } } } @@ -381,7 +393,7 @@ func (cb KeyboardInteractiveChallenge) method() string { return "keyboard-interactive" } -func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { type initiateMsg struct { User string `sshtype:"50"` Service string @@ -395,20 +407,20 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe Service: serviceSSH, Method: "keyboard-interactive", })); err != nil { - return false, nil, err + return authFailure, nil, err } for { packet, err := c.readPacket() if err != nil { - return false, nil, err + return authFailure, nil, err } // like handleAuthResponse, but with less options. switch packet[0] { case msgUserAuthBanner: if err := handleBannerResponse(c, packet); err != nil { - return false, nil, err + return authFailure, nil, err } continue case msgUserAuthInfoRequest: @@ -416,18 +428,21 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe case msgUserAuthFailure: var msg userAuthFailureMsg if err := Unmarshal(packet, &msg); err != nil { - return false, nil, err + return authFailure, nil, err } - return false, msg.Methods, nil + if msg.PartialSuccess { + return authPartialSuccess, msg.Methods, nil + } + return authFailure, msg.Methods, nil case msgUserAuthSuccess: - return true, nil, nil + return authSuccess, nil, nil default: - return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) } var msg userAuthInfoRequestMsg if err := Unmarshal(packet, &msg); err != nil { - return false, nil, err + return authFailure, nil, err } // Manually unpack the prompt/echo pairs. @@ -437,7 +452,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe for i := 0; i < int(msg.NumPrompts); i++ { prompt, r, ok := parseString(rest) if !ok || len(r) == 0 { - return false, nil, errors.New("ssh: prompt format error") + return authFailure, nil, errors.New("ssh: prompt format error") } prompts = append(prompts, string(prompt)) echos = append(echos, r[0] != 0) @@ -445,16 +460,16 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe } if len(rest) != 0 { - return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs") + return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") } answers, err := cb(msg.User, msg.Instruction, prompts, echos) if err != nil { - return false, nil, err + return authFailure, nil, err } if len(answers) != len(prompts) { - return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") + return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") } responseLength := 1 + 4 for _, a := range answers { @@ -470,7 +485,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe } if err := c.writePacket(serialized); err != nil { - return false, nil, err + return authFailure, nil, err } } } @@ -480,10 +495,10 @@ type retryableAuthMethod struct { maxTries int } -func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) { +func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) { for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { ok, methods, err = r.authMethod.auth(session, user, c, rand) - if ok || err != nil { // either success or error terminate + if ok != authFailure || err != nil { // either success, partial success or error terminate return ok, methods, err } } diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go index 145b57a..5fbb20d 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth_test.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go @@ -614,8 +614,8 @@ func TestClientAuthErrorList(t *testing.T) { for i, e := range authErrs.Errors { switch i { case 0: - if e.Error() != "no auth passed yet" { - t.Fatalf("errors: got %v, want no auth passed yet", e.Error()) + if e != ErrNoAuth { + t.Fatalf("errors: got error %v, want ErrNoAuth", e) } case 1: if e != publicKeyErr { diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go index 77f9c5b..04f3620 100644 --- a/vendor/golang.org/x/crypto/ssh/common.go +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -24,12 +24,21 @@ const ( serviceSSH = "ssh-connection" ) -// supportedCiphers specifies the supported ciphers in preference order. +// supportedCiphers lists ciphers we support but might not recommend. var supportedCiphers = []string{ "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", chacha20Poly1305ID, - "arcfour256", "arcfour128", + "arcfour256", "arcfour128", "arcfour", + aes128cbcID, + tripledescbcID, +} + +// preferredCiphers specifies the default preference for ciphers. +var preferredCiphers = []string{ + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "aes128-ctr", "aes192-ctr", "aes256-ctr", } // supportedKexAlgos specifies the supported key-exchange algorithms in @@ -212,7 +221,7 @@ func (c *Config) SetDefaults() { c.Rand = rand.Reader } if c.Ciphers == nil { - c.Ciphers = supportedCiphers + c.Ciphers = preferredCiphers } var ciphers []string for _, c := range c.Ciphers { diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index dadf41a..34d9582 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -276,7 +276,8 @@ type PublicKey interface { Type() string // Marshal returns the serialized key data in SSH wire format, - // with the name prefix. + // with the name prefix. To unmarshal the returned data, use + // the ParsePublicKey function. Marshal() []byte // Verify that sig is a signature on the given data using this @@ -802,7 +803,7 @@ func encryptedBlock(block *pem.Block) bool { } // ParseRawPrivateKey returns a private key from a PEM encoded private key. It -// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. +// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { block, _ := pem.Decode(pemBytes) if block == nil { @@ -816,6 +817,9 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { switch block.Type { case "RSA PRIVATE KEY": return x509.ParsePKCS1PrivateKey(block.Bytes) + // RFC5208 - https://tools.ietf.org/html/rfc5208 + case "PRIVATE KEY": + return x509.ParsePKCS8PrivateKey(block.Bytes) case "EC PRIVATE KEY": return x509.ParseECPrivateKey(block.Bytes) case "DSA PRIVATE KEY": diff --git a/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/golang.org/x/crypto/ssh/keys_test.go index 20ab954..9a90abc 100644 --- a/vendor/golang.org/x/crypto/ssh/keys_test.go +++ b/vendor/golang.org/x/crypto/ssh/keys_test.go @@ -234,7 +234,7 @@ func TestMarshalParsePublicKey(t *testing.T) { } } -type authResult struct { +type testAuthResult struct { pubKey PublicKey options []string comments string @@ -242,11 +242,11 @@ type authResult struct { ok bool } -func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) { +func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) { rest := authKeys - var values []authResult + var values []testAuthResult for len(rest) > 0 { - var r authResult + var r testAuthResult var err error r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) r.ok = (err == nil) @@ -264,7 +264,7 @@ func TestAuthorizedKeyBasic(t *testing.T) { pub, pubSerialized := getTestKey() line := "ssh-rsa " + pubSerialized + " user@host" testAuthorizedKeys(t, []byte(line), - []authResult{ + []testAuthResult{ {pub, nil, "user@host", "", true}, }) } @@ -286,7 +286,7 @@ func TestAuth(t *testing.T) { authOptions := strings.Join(authWithOptions, eol) rest2 := strings.Join(authWithOptions[3:], eol) rest3 := strings.Join(authWithOptions[6:], eol) - testAuthorizedKeys(t, []byte(authOptions), []authResult{ + testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{ {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, {nil, nil, "", "", false}, @@ -297,7 +297,7 @@ func TestAuth(t *testing.T) { func TestAuthWithQuotedSpaceInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{ + testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{ {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, }) } @@ -305,7 +305,7 @@ func TestAuthWithQuotedSpaceInEnv(t *testing.T) { func TestAuthWithQuotedCommaInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{ + testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{ {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, }) } @@ -314,11 +314,11 @@ func TestAuthWithQuotedQuoteInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{ + testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{ {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, }) - testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{ + testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{ {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, }) } @@ -327,7 +327,7 @@ func TestAuthWithInvalidSpace(t *testing.T) { _, pubSerialized := getTestKey() authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host #more to follow but still no valid keys`) - testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{ + testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{ {nil, nil, "", "", false}, }) } @@ -337,7 +337,7 @@ func TestAuthWithMissingQuote(t *testing.T) { authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) - testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{ + testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{ {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, }) } diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go index 448fc07..bc3db73 100644 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package knownhosts implements a parser for the OpenSSH -// known_hosts host key database. +// Package knownhosts implements a parser for the OpenSSH known_hosts +// host key database, and provides utility functions for writing +// OpenSSH compliant known_hosts files. package knownhosts import ( @@ -38,7 +39,7 @@ func (a *addr) String() string { } type matcher interface { - match([]addr) bool + match(addr) bool } type hostPattern struct { @@ -57,19 +58,16 @@ func (p *hostPattern) String() string { type hostPatterns []hostPattern -func (ps hostPatterns) match(addrs []addr) bool { +func (ps hostPatterns) match(a addr) bool { matched := false for _, p := range ps { - for _, a := range addrs { - m := p.match(a) - if !m { - continue - } - if p.negate { - return false - } - matched = true + if !p.match(a) { + continue } + if p.negate { + return false + } + matched = true } return matched } @@ -122,8 +120,8 @@ func serialize(k ssh.PublicKey) string { return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) } -func (l *keyDBLine) match(addrs []addr) bool { - return l.matcher.match(addrs) +func (l *keyDBLine) match(a addr) bool { + return l.matcher.match(a) } type hostKeyDB struct { @@ -153,7 +151,7 @@ func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool a := addr{host: h, port: p} for _, l := range db.lines { - if l.cert && keyEq(l.knownKey.Key, remote) && l.match([]addr{a}) { + if l.cert && keyEq(l.knownKey.Key, remote) && l.match(a) { return true } } @@ -338,26 +336,24 @@ func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.Public return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err) } - addrs := []addr{ - {host, port}, - } - + hostToCheck := addr{host, port} if address != "" { + // Give preference to the hostname if available. host, port, err := net.SplitHostPort(address) if err != nil { return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err) } - addrs = append(addrs, addr{host, port}) + hostToCheck = addr{host, port} } - return db.checkAddrs(addrs, remoteKey) + return db.checkAddr(hostToCheck, remoteKey) } // checkAddrs checks if we can find the given public key for any of // the given addresses. If we only find an entry for the IP address, // or only the hostname, then this still succeeds. -func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error { +func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { // TODO(hanwen): are these the right semantics? What if there // is just a key for the IP address, but not for the // hostname? @@ -365,7 +361,7 @@ func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error { // Algorithm => key. knownKeys := map[string]KnownKey{} for _, l := range db.lines { - if l.match(addrs) { + if l.match(a) { typ := l.knownKey.Key.Type() if _, ok := knownKeys[typ]; !ok { knownKeys[typ] = l.knownKey @@ -414,7 +410,10 @@ func (db *hostKeyDB) Read(r io.Reader, filename string) error { // New creates a host key callback from the given OpenSSH host key // files. The returned callback is for use in -// ssh.ClientConfig.HostKeyCallback. Hashed hostnames are not supported. +// ssh.ClientConfig.HostKeyCallback. By preference, the key check +// operates on the hostname if available, i.e. if a server changes its +// IP address, the host key check will still succeed, even though a +// record of the new IP address is not available. func New(files ...string) (ssh.HostKeyCallback, error) { db := newHostKeyDB() for _, fn := range files { @@ -536,11 +535,6 @@ func newHashedHost(encoded string) (*hashedHost, error) { return &hashedHost{salt: salt, hash: hash}, nil } -func (h *hashedHost) match(addrs []addr) bool { - for _, a := range addrs { - if bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) { - return true - } - } - return false +func (h *hashedHost) match(a addr) bool { + return bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) } diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go index be7cc0e..464dd59 100644 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go @@ -166,7 +166,7 @@ func TestBasic(t *testing.T) { str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr) db := testDB(t, str) if err := db.check("server.org:22", testAddr, edKey); err != nil { - t.Errorf("got error %q, want none", err) + t.Errorf("got error %v, want none", err) } want := KnownKey{ @@ -185,6 +185,33 @@ func TestBasic(t *testing.T) { } } +func TestHostNamePrecedence(t *testing.T) { + var evilAddr = &net.TCPAddr{ + IP: net.IP{66, 66, 66, 66}, + Port: 22, + } + + str := fmt.Sprintf("server.org,%s %s\nevil.org,%s %s", testAddr, edKeyStr, evilAddr, ecKeyStr) + db := testDB(t, str) + + if err := db.check("server.org:22", evilAddr, ecKey); err == nil { + t.Errorf("check succeeded") + } else if _, ok := err.(*KeyError); !ok { + t.Errorf("got %T, want *KeyError", err) + } +} + +func TestDBOrderingPrecedenceKeyType(t *testing.T) { + str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) + db := testDB(t, str) + + if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { + t.Errorf("check succeeded") + } else if _, ok := err.(*KeyError); !ok { + t.Errorf("got %T, want *KeyError", err) + } +} + func TestNegate(t *testing.T) { str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) db := testDB(t, str) diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go index 25d2181..d88b64e 100644 --- a/vendor/golang.org/x/crypto/ssh/mux_test.go +++ b/vendor/golang.org/x/crypto/ssh/mux_test.go @@ -108,10 +108,6 @@ func TestMuxReadWrite(t *testing.T) { if err != nil { t.Fatalf("Write: %v", err) } - err = s.Close() - if err != nil { - t.Fatalf("Close: %v", err) - } }() var buf [1024]byte diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index b83d473..d0f4825 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -166,6 +166,9 @@ type ServerConn struct { // unsuccessful, it closes the connection and returns an error. The // Request and NewChannel channels must be serviced, or the connection // will hang. +// +// The returned error may be of type *ServerAuthError for +// authentication errors. func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { fullConf := *config fullConf.SetDefaults() @@ -292,12 +295,13 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) } -// ServerAuthError implements the error interface. It appends any authentication -// errors that may occur, and is returned if all of the authentication methods -// provided by the user failed to authenticate. +// ServerAuthError represents server authentication errors and is +// sometimes returned by NewServerConn. It appends any authentication +// errors that may occur, and is returned if all of the authentication +// methods provided by the user failed to authenticate. type ServerAuthError struct { // Errors contains authentication errors returned by the authentication - // callback methods. + // callback methods. The first entry is typically ErrNoAuth. Errors []error } @@ -309,6 +313,13 @@ func (l ServerAuthError) Error() string { return "[" + strings.Join(errs, ", ") + "]" } +// ErrNoAuth is the error value returned if no +// authentication method has been passed yet. This happens as a normal +// part of the authentication loop, since the client first tries +// 'none' authentication to discover available methods. +// It is returned in ServerAuthError.Errors from NewServerConn. +var ErrNoAuth = errors.New("ssh: no auth passed yet") + func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { sessionID := s.transport.getSessionID() var cache pubKeyCache @@ -363,7 +374,7 @@ userAuthLoop: } perms = nil - authErr := errors.New("no auth passed yet") + authErr := ErrNoAuth switch userAuthReq.Method { case "none": diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go index a2dccc6..b171b33 100644 --- a/vendor/golang.org/x/crypto/ssh/streamlocal.go +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -32,6 +32,7 @@ type streamLocalChannelForwardMsg struct { // ListenUnix is similar to ListenTCP but uses a Unix domain socket. func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) m := streamLocalChannelForwardMsg{ socketPath, } diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index acf1717..80d35f5 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -90,10 +90,19 @@ type channelForwardMsg struct { rport uint32 } +// handleForwards starts goroutines handling forwarded connections. +// It's called on first use by (*Client).ListenTCP to not launch +// goroutines until needed. +func (c *Client) handleForwards() { + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) +} + // ListenTCP requests the remote peer open a listening socket // on laddr. Incoming connections will be available by calling // Accept on the returned net.Listener. func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { return c.autoPortListenWorkaround(laddr) } diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go index 901c72a..d9b77c1 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go @@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd windows plan9 solaris + package terminal import ( "bytes" "io" "os" + "runtime" "testing" ) @@ -324,6 +327,11 @@ func TestMakeRawState(t *testing.T) { if err != nil { t.Fatalf("failed to get terminal state from GetState: %s", err) } + + if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { + t.Skip("MakeRaw not allowed on iOS; skipping test") + } + defer Restore(fd, st) raw, err := MakeRaw(fd) if err != nil { diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go index 02dad48..731c89a 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/util.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go @@ -108,9 +108,7 @@ func ReadPassword(fd int) ([]byte, error) { return nil, err } - defer func() { - unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) - }() + defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) return readPasswordLine(passwordReader(fd)) } diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go index a2e1b57..9e41b9f 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go @@ -14,7 +14,7 @@ import ( // State contains the state of a terminal. type State struct { - state *unix.Termios + termios unix.Termios } // IsTerminal returns true if the given file descriptor is a terminal. @@ -75,47 +75,43 @@ func ReadPassword(fd int) ([]byte, error) { // restored. // see http://cr.illumos.org/~webrev/andy_js/1060/ func MakeRaw(fd int) (*State, error) { - oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } - oldTermios := *oldTermiosPtr - newTermios := oldTermios - newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON - newTermios.Oflag &^= syscall.OPOST - newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN - newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB - newTermios.Cflag |= syscall.CS8 - newTermios.Cc[unix.VMIN] = 1 - newTermios.Cc[unix.VTIME] = 0 + oldState := State{termios: *termios} - if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil { + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + + if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil { return nil, err } - return &State{ - state: oldTermiosPtr, - }, nil + return &oldState, nil } // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, oldState *State) error { - return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state) + return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) } // GetState returns the current state of a terminal which may be useful to // restore the terminal after a signal. func GetState(fd int) (*State, error) { - oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } - return &State{ - state: oldTermiosPtr, - }, nil + return &State{termios: *termios}, nil } // GetSize returns the dimensions of the given terminal. diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go index 92944f3..8618955 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -89,9 +89,15 @@ func ReadPassword(fd int) ([]byte, error) { return nil, err } - defer func() { - windows.SetConsoleMode(windows.Handle(fd), old) - }() + defer windows.SetConsoleMode(windows.Handle(fd), old) - return readPasswordLine(os.NewFile(uintptr(fd), "stdin")) + var h windows.Handle + p, _ := windows.GetCurrentProcess() + if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { + return nil, err + } + + f := os.NewFile(uintptr(h), "stdin") + defer f.Close() + return readPasswordLine(f) } diff --git a/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go b/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go new file mode 100644 index 0000000..f594d36 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go @@ -0,0 +1,144 @@ +// Copyright 2017 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. + +// Tests for ssh client multi-auth +// +// These tests run a simple go ssh client against OpenSSH server +// over unix domain sockets. The tests use multiple combinations +// of password, keyboard-interactive and publickey authentication +// methods. +// +// A wrapper library for making sshd PAM authentication use test +// passwords is required in ./sshd_test_pw.so. If the library does +// not exist these tests will be skipped. See compile instructions +// (for linux) in file ./sshd_test_pw.c. + +// +build linux + +package test + +import ( + "fmt" + "strings" + "testing" + + "golang.org/x/crypto/ssh" +) + +// test cases +type multiAuthTestCase struct { + authMethods []string + expectedPasswordCbs int + expectedKbdIntCbs int +} + +// test context +type multiAuthTestCtx struct { + password string + numPasswordCbs int + numKbdIntCbs int +} + +// create test context +func newMultiAuthTestCtx(t *testing.T) *multiAuthTestCtx { + password, err := randomPassword() + if err != nil { + t.Fatalf("Failed to generate random test password: %s", err.Error()) + } + + return &multiAuthTestCtx{ + password: password, + } +} + +// password callback +func (ctx *multiAuthTestCtx) passwordCb() (secret string, err error) { + ctx.numPasswordCbs++ + return ctx.password, nil +} + +// keyboard-interactive callback +func (ctx *multiAuthTestCtx) kbdIntCb(user, instruction string, questions []string, echos []bool) (answers []string, err error) { + if len(questions) == 0 { + return nil, nil + } + + ctx.numKbdIntCbs++ + if len(questions) == 1 { + return []string{ctx.password}, nil + } + + return nil, fmt.Errorf("unsupported keyboard-interactive flow") +} + +// TestMultiAuth runs several subtests for different combinations of password, keyboard-interactive and publickey authentication methods +func TestMultiAuth(t *testing.T) { + testCases := []multiAuthTestCase{ + // Test password,publickey authentication, assert that password callback is called 1 time + multiAuthTestCase{ + authMethods: []string{"password", "publickey"}, + expectedPasswordCbs: 1, + }, + // Test keyboard-interactive,publickey authentication, assert that keyboard-interactive callback is called 1 time + multiAuthTestCase{ + authMethods: []string{"keyboard-interactive", "publickey"}, + expectedKbdIntCbs: 1, + }, + // Test publickey,password authentication, assert that password callback is called 1 time + multiAuthTestCase{ + authMethods: []string{"publickey", "password"}, + expectedPasswordCbs: 1, + }, + // Test publickey,keyboard-interactive authentication, assert that keyboard-interactive callback is called 1 time + multiAuthTestCase{ + authMethods: []string{"publickey", "keyboard-interactive"}, + expectedKbdIntCbs: 1, + }, + // Test password,password authentication, assert that password callback is called 2 times + multiAuthTestCase{ + authMethods: []string{"password", "password"}, + expectedPasswordCbs: 2, + }, + } + + for _, testCase := range testCases { + t.Run(strings.Join(testCase.authMethods, ","), func(t *testing.T) { + ctx := newMultiAuthTestCtx(t) + + server := newServerForConfig(t, "MultiAuth", map[string]string{"AuthMethods": strings.Join(testCase.authMethods, ",")}) + defer server.Shutdown() + + clientConfig := clientConfig() + server.setTestPassword(clientConfig.User, ctx.password) + + publicKeyAuthMethod := clientConfig.Auth[0] + clientConfig.Auth = nil + for _, authMethod := range testCase.authMethods { + switch authMethod { + case "publickey": + clientConfig.Auth = append(clientConfig.Auth, publicKeyAuthMethod) + case "password": + clientConfig.Auth = append(clientConfig.Auth, + ssh.RetryableAuthMethod(ssh.PasswordCallback(ctx.passwordCb), 5)) + case "keyboard-interactive": + clientConfig.Auth = append(clientConfig.Auth, + ssh.RetryableAuthMethod(ssh.KeyboardInteractive(ctx.kbdIntCb), 5)) + default: + t.Fatalf("Unknown authentication method %s", authMethod) + } + } + + conn := server.Dial(clientConfig) + defer conn.Close() + + if ctx.numPasswordCbs != testCase.expectedPasswordCbs { + t.Fatalf("passwordCallback was called %d times, expected %d times", ctx.numPasswordCbs, testCase.expectedPasswordCbs) + } + + if ctx.numKbdIntCbs != testCase.expectedKbdIntCbs { + t.Fatalf("keyboardInteractiveCallback was called %d times, expected %d times", ctx.numKbdIntCbs, testCase.expectedKbdIntCbs) + } + }) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/golang.org/x/crypto/ssh/test/session_test.go index 9e702ef..4eb7afd 100644 --- a/vendor/golang.org/x/crypto/ssh/test/session_test.go +++ b/vendor/golang.org/x/crypto/ssh/test/session_test.go @@ -11,6 +11,7 @@ package test import ( "bytes" "errors" + "fmt" "io" "strings" "testing" @@ -324,31 +325,59 @@ func TestWindowChange(t *testing.T) { } } +func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + conf.Ciphers = []string{cipher} + // Don't fail if sshd doesn't have the cipher. + conf.Ciphers = append(conf.Ciphers, cipherOrder...) + conn, err := server.TryDial(conf) + if err != nil { + t.Fatalf("TryDial: %v", err) + } + defer conn.Close() + + numBytes := 4096 + + // Exercise sending data to the server + if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { + t.Fatalf("SendRequest: %v", err) + } + + // Exercise receiving data from the server + session, err := conn.NewSession() + if err != nil { + t.Fatalf("NewSession: %v", err) + } + + out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes)) + if err != nil { + t.Fatalf("Output: %v", err) + } + + if len(out) != numBytes { + t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) + } +} + +var deprecatedCiphers = []string{ + "aes128-cbc", "3des-cbc", + "arcfour128", "arcfour256", +} + func TestCiphers(t *testing.T) { var config ssh.Config config.SetDefaults() - cipherOrder := config.Ciphers - // These ciphers will not be tested when commented out in cipher.go it will - // fallback to the next available as per line 292. - cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc") + cipherOrder := append(config.Ciphers, deprecatedCiphers...) for _, ciph := range cipherOrder { t.Run(ciph, func(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - conf.Ciphers = []string{ciph} - // Don't fail if sshd doesn't have the cipher. - conf.Ciphers = append(conf.Ciphers, cipherOrder...) - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - } else { - t.Fatalf("failed for cipher %q", ciph) - } + testOneCipher(t, ciph, cipherOrder) }) } } + func TestMACs(t *testing.T) { var config ssh.Config config.SetDefaults() diff --git a/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c b/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c new file mode 100644 index 0000000..2794a56 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c @@ -0,0 +1,173 @@ +// Copyright 2017 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. + +// sshd_test_pw.c +// Wrapper to inject test password data for sshd PAM authentication +// +// This wrapper implements custom versions of getpwnam, getpwnam_r, +// getspnam and getspnam_r. These functions first call their real +// libc versions, then check if the requested user matches test user +// specified in env variable TEST_USER and if so replace the password +// with crypted() value of TEST_PASSWD env variable. +// +// Compile: +// gcc -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c +// +// Compile with debug: +// gcc -DVERBOSE -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c +// +// Run sshd: +// LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ... + +// +build ignore + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#ifdef VERBOSE +#define DEBUG(X...) fprintf(stderr, X) +#else +#define DEBUG(X...) while (0) { } +#endif + +/* crypt() password */ +static char * +pwhash(char *passwd) { + return strdup(crypt(passwd, "$6$")); +} + +/* Pointers to real functions in libc */ +static struct passwd * (*real_getpwnam)(const char *) = NULL; +static int (*real_getpwnam_r)(const char *, struct passwd *, char *, size_t, struct passwd **) = NULL; +static struct spwd * (*real_getspnam)(const char *) = NULL; +static int (*real_getspnam_r)(const char *, struct spwd *, char *, size_t, struct spwd **) = NULL; + +/* Cached test user and test password */ +static char *test_user = NULL; +static char *test_passwd_hash = NULL; + +static void +init(void) { + /* Fetch real libc function pointers */ + real_getpwnam = dlsym(RTLD_NEXT, "getpwnam"); + real_getpwnam_r = dlsym(RTLD_NEXT, "getpwnam_r"); + real_getspnam = dlsym(RTLD_NEXT, "getspnam"); + real_getspnam_r = dlsym(RTLD_NEXT, "getspnam_r"); + + /* abort if env variables are not defined */ + if (getenv("TEST_USER") == NULL || getenv("TEST_PASSWD") == NULL) { + fprintf(stderr, "env variables TEST_USER and TEST_PASSWD are missing\n"); + abort(); + } + + /* Fetch test user and test password from env */ + test_user = strdup(getenv("TEST_USER")); + test_passwd_hash = pwhash(getenv("TEST_PASSWD")); + + DEBUG("sshd_test_pw init():\n"); + DEBUG("\treal_getpwnam: %p\n", real_getpwnam); + DEBUG("\treal_getpwnam_r: %p\n", real_getpwnam_r); + DEBUG("\treal_getspnam: %p\n", real_getspnam); + DEBUG("\treal_getspnam_r: %p\n", real_getspnam_r); + DEBUG("\tTEST_USER: '%s'\n", test_user); + DEBUG("\tTEST_PASSWD: '%s'\n", getenv("TEST_PASSWD")); + DEBUG("\tTEST_PASSWD_HASH: '%s'\n", test_passwd_hash); +} + +static int +is_test_user(const char *name) { + if (test_user != NULL && strcmp(test_user, name) == 0) + return 1; + return 0; +} + +/* getpwnam */ + +struct passwd * +getpwnam(const char *name) { + struct passwd *pw; + + DEBUG("sshd_test_pw getpwnam(%s)\n", name); + + if (real_getpwnam == NULL) + init(); + if ((pw = real_getpwnam(name)) == NULL) + return NULL; + + if (is_test_user(name)) + pw->pw_passwd = strdup(test_passwd_hash); + + return pw; +} + +/* getpwnam_r */ + +int +getpwnam_r(const char *name, + struct passwd *pwd, + char *buf, + size_t buflen, + struct passwd **result) { + int r; + + DEBUG("sshd_test_pw getpwnam_r(%s)\n", name); + + if (real_getpwnam_r == NULL) + init(); + if ((r = real_getpwnam_r(name, pwd, buf, buflen, result)) != 0 || *result == NULL) + return r; + + if (is_test_user(name)) + pwd->pw_passwd = strdup(test_passwd_hash); + + return 0; +} + +/* getspnam */ + +struct spwd * +getspnam(const char *name) { + struct spwd *sp; + + DEBUG("sshd_test_pw getspnam(%s)\n", name); + + if (real_getspnam == NULL) + init(); + if ((sp = real_getspnam(name)) == NULL) + return NULL; + + if (is_test_user(name)) + sp->sp_pwdp = strdup(test_passwd_hash); + + return sp; +} + +/* getspnam_r */ + +int +getspnam_r(const char *name, + struct spwd *spbuf, + char *buf, + size_t buflen, + struct spwd **spbufp) { + int r; + + DEBUG("sshd_test_pw getspnam_r(%s)\n", name); + + if (real_getspnam_r == NULL) + init(); + if ((r = real_getspnam_r(name, spbuf, buf, buflen, spbufp)) != 0) + return r; + + if (is_test_user(name)) + spbuf->sp_pwdp = strdup(test_passwd_hash); + + return r; +} diff --git a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go index 15b879d..2fbe880 100644 --- a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go +++ b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go @@ -10,6 +10,8 @@ package test import ( "bytes" + "crypto/rand" + "encoding/base64" "fmt" "io/ioutil" "log" @@ -25,7 +27,8 @@ import ( "golang.org/x/crypto/ssh/testdata" ) -const sshdConfig = ` +const ( + defaultSshdConfig = ` Protocol 2 Banner {{.Dir}}/banner HostKey {{.Dir}}/id_rsa @@ -50,8 +53,17 @@ RhostsRSAAuthentication no HostbasedAuthentication no PubkeyAcceptedKeyTypes=* ` + multiAuthSshdConfigTail = ` +UsePAM yes +PasswordAuthentication yes +ChallengeResponseAuthentication yes +AuthenticationMethods {{.AuthMethods}} +` +) -var configTmpl = template.Must(template.New("").Parse(sshdConfig)) +var configTmpl = map[string]*template.Template{ + "default": template.Must(template.New("").Parse(defaultSshdConfig)), + "MultiAuth": template.Must(template.New("").Parse(defaultSshdConfig + multiAuthSshdConfigTail))} type server struct { t *testing.T @@ -60,6 +72,10 @@ type server struct { cmd *exec.Cmd output bytes.Buffer // holds stderr from sshd process + testUser string // test username for sshd + testPasswd string // test password for sshd + sshdTestPwSo string // dynamic library to inject a custom password into sshd + // Client half of the network connection. clientConn net.Conn } @@ -186,6 +202,20 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl s.cmd.Stdin = f s.cmd.Stdout = f s.cmd.Stderr = &s.output + + if s.sshdTestPwSo != "" { + if s.testUser == "" { + s.t.Fatal("user missing from sshd_test_pw.so config") + } + if s.testPasswd == "" { + s.t.Fatal("password missing from sshd_test_pw.so config") + } + s.cmd.Env = append(os.Environ(), + fmt.Sprintf("LD_PRELOAD=%s", s.sshdTestPwSo), + fmt.Sprintf("TEST_USER=%s", s.testUser), + fmt.Sprintf("TEST_PASSWD=%s", s.testPasswd)) + } + if err := s.cmd.Start(); err != nil { s.t.Fail() s.Shutdown() @@ -236,11 +266,49 @@ func writeFile(path string, contents []byte) { } } +// generate random password +func randomPassword() (string, error) { + b := make([]byte, 12) + _, err := rand.Read(b) + if err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + +// setTestPassword is used for setting user and password data for sshd_test_pw.so +// This function also checks that ./sshd_test_pw.so exists and if not calls s.t.Skip() +func (s *server) setTestPassword(user, passwd string) error { + wd, _ := os.Getwd() + wrapper := filepath.Join(wd, "sshd_test_pw.so") + if _, err := os.Stat(wrapper); err != nil { + s.t.Skip(fmt.Errorf("sshd_test_pw.so is not available")) + return err + } + + s.sshdTestPwSo = wrapper + s.testUser = user + s.testPasswd = passwd + return nil +} + // newServer returns a new mock ssh server. func newServer(t *testing.T) *server { + return newServerForConfig(t, "default", map[string]string{}) +} + +// newServerForConfig returns a new mock ssh server. +func newServerForConfig(t *testing.T, config string, configVars map[string]string) *server { if testing.Short() { t.Skip("skipping test due to -short") } + u, err := user.Current() + if err != nil { + t.Fatalf("user.Current: %v", err) + } + if u.Name == "root" { + t.Skip("skipping test because current user is root") + } dir, err := ioutil.TempDir("", "sshtest") if err != nil { t.Fatal(err) @@ -249,9 +317,11 @@ func newServer(t *testing.T) *server { if err != nil { t.Fatal(err) } - err = configTmpl.Execute(f, map[string]string{ - "Dir": dir, - }) + if _, ok := configTmpl[config]; ok == false { + t.Fatal(fmt.Errorf("Invalid server config '%s'", config)) + } + configVars["Dir"] = dir + err = configTmpl[config].Execute(f, configVars) if err != nil { t.Fatal(err) } diff --git a/vendor/golang.org/x/crypto/ssh/testdata/keys.go b/vendor/golang.org/x/crypto/ssh/testdata/keys.go index 521b6be..bdaa9cb 100644 --- a/vendor/golang.org/x/crypto/ssh/testdata/keys.go +++ b/vendor/golang.org/x/crypto/ssh/testdata/keys.go @@ -60,6 +60,35 @@ NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= -----END RSA PRIVATE KEY----- +`), + "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCitzS2KiRQTccf +VApb0mbPpo1lt29JjeLBYAehXHWfQ+w8sXpd8e04n/020spx1R94yg+v0NjXyh2R +NFXNBYdhNei33VJxUeKNlExaecvW2yxfuZqka+ZxT1aI8zrAsjh3Rwc6wayAJS4R +wZuzlDv4jZitWqwD+mb/22Zwq/WSs4YX5dUHDklfdWSVnoBfue8K/00n8f5yMTdJ +vFF0qAJwf9spPEHla0lYcozJk64CO5lRkqfLor4UnsXXOiA7aRIoaUSKa+rlhiqt +1EMGYiBjblPt4SwMelGGU2UfywPb4d85gpQ/s8SBARbpPxNVs2IbHDMwj70P3uZc +74M3c4VJAgMBAAECggEAFIzY3mziGzZHgMBncoNXMsCRORh6uKpvygZr0EhSHqRA +cMXlc3n7gNxL6aGjqc7F48Z5RrY0vMQtCcq3T2Z0W6WoV5hfMiqqV0E0h3S8ds1F +hG13h26NMyBXCILXl8Cqev4Afr45IBISCHIQTRTaoiCX+MTr1rDIU2YNQQumvzkz +fMw2XiFTFTgxAtJUAgKoTqLtm7/T+az7TKw+Hesgbx7yaJoMh9DWGBh4Y61DnIDA +fcxJboAfxxnFiXvdBVmzo72pCsRXrWOsjW6WxQmCKuXHvyB1FZTmMaEFNCGSJDa6 +U+OCzA3m65loAZAE7ffFHhYgssz/h9TBaOjKO0BX1QKBgQDZiCBvu+bFh9pEodcS +VxaI+ATlsYcmGdLtnZw5pxuEdr60iNWhpEcV6lGkbdiv5aL43QaGFDLagqeHI77b ++ITFbPPdCiYNaqlk6wyiXv4pdN7V683EDmGWSQlPeC9IhUilt2c+fChK2EB/XlkO +q8c3Vk1MsC6JOxDXNgJxylNpswKBgQC/fYBTb9iD+uM2n3SzJlct/ZlPaONKnNDR +pbTOdxBFHsu2VkfY858tfnEPkmSRX0yKmjHni6e8/qIzfzLwWBY4NmxhNZE5v+qJ +qZF26ULFdrZB4oWXAOliy/1S473OpQnp2MZp2asd0LPcg/BNaMuQrz44hxHb76R7 +qWD0ebIfEwKBgQCRCIiP1pjbVGN7ZOgPS080DSC+wClahtcyI+ZYLglTvRQTLDQ7 +LFtUykCav748MIADKuJBnM/3DiuCF5wV71EejDDfS/fo9BdyuKBY1brhixFTUX+E +Ww5Hc/SoLnpgALVZ/7jvWTpIBHykLxRziqYtR/YLzl+IkX/97P2ePoZ0rwKBgHNC +/7M5Z4JJyepfIMeVFHTCaT27TNTkf20x6Rs937U7TDN8y9JzEiU4LqXI4HAAhPoI +xnExRs4kF04YCnlRDE7Zs3Lv43J3ap1iTATfcymYwyv1RaQXEGQ/lUQHgYCZJtZz +fTrJoo5XyWu6nzJ5Gc8FLNaptr5ECSXGVm3Rsr2xAoGBAJWqEEQS/ejhO05QcPqh +y4cUdLr0269ILVsvic4Ot6zgfPIntXAK6IsHGKcg57kYm6W9k1CmmlA4ENGryJnR +vxyyqA9eyTFc1CQNuc2frKFA9It49JzjXahKc0aDHEHmTR787Tmk1LbuT0/gm9kA +L4INU6g+WqF0fatJxd+IJPrp +-----END PRIVATE KEY----- `), "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go index 5a56753..f6fae1d 100644 --- a/vendor/golang.org/x/crypto/ssh/transport.go +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -233,51 +233,22 @@ var ( clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} ) -// generateKeys generates key material for IV, MAC and encryption. -func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { - cipherMode := cipherModes[algs.Cipher] - macMode := macModes[algs.MAC] - - iv = make([]byte, cipherMode.ivSize) - key = make([]byte, cipherMode.keySize) - macKey = make([]byte, macMode.keySize) - - generateKeyMaterial(iv, d.ivTag, kex) - generateKeyMaterial(key, d.keyTag, kex) - generateKeyMaterial(macKey, d.macKeyTag, kex) - return -} - // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // described in RFC 4253, section 6.4. direction should either be serverKeys // (to setup server->client keys) or clientKeys (for client->server keys). func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { - iv, key, macKey := generateKeys(d, algs, kex) + cipherMode := cipherModes[algs.Cipher] + macMode := macModes[algs.MAC] - switch algs.Cipher { - case chacha20Poly1305ID: - return newChaCha20Cipher(key) - case gcmCipherID: - return newGCMCipher(iv, key) - case aes128cbcID: - return newAESCBCCipher(iv, key, macKey, algs) - case tripledescbcID: - return newTripleDESCBCCipher(iv, key, macKey, algs) - } + iv := make([]byte, cipherMode.ivSize) + key := make([]byte, cipherMode.keySize) + macKey := make([]byte, macMode.keySize) - c := &streamPacketCipher{ - mac: macModes[algs.MAC].new(macKey), - etm: macModes[algs.MAC].etm, - } - c.macResult = make([]byte, c.mac.Size()) + generateKeyMaterial(iv, d.ivTag, kex) + generateKeyMaterial(key, d.keyTag, kex) + generateKeyMaterial(macKey, d.macKeyTag, kex) - var err error - c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) - if err != nil { - return nil, err - } - - return c, nil + return cipherModes[algs.Cipher].create(key, iv, macKey, algs) } // generateKeyMaterial fills out with key material generated from tag, K, H diff --git a/vendor/golang.org/x/crypto/xtea/block.go b/vendor/golang.org/x/crypto/xtea/block.go index bf5d245..fcb4e4d 100644 --- a/vendor/golang.org/x/crypto/xtea/block.go +++ b/vendor/golang.org/x/crypto/xtea/block.go @@ -50,7 +50,7 @@ func encryptBlock(c *Cipher, dst, src []byte) { uint32ToBlock(v0, v1, dst) } -// decryptBlock decrypt a single 8 byte block using XTEA. +// decryptBlock decrypts a single 8 byte block using XTEA. func decryptBlock(c *Cipher, dst, src []byte) { v0, v1 := blockToUint32(src) diff --git a/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/golang.org/x/crypto/xtea/cipher.go index 66ea0df..1661cbe 100644 --- a/vendor/golang.org/x/crypto/xtea/cipher.go +++ b/vendor/golang.org/x/crypto/xtea/cipher.go @@ -14,8 +14,8 @@ import "strconv" const BlockSize = 8 // A Cipher is an instance of an XTEA cipher using a particular key. -// table contains a series of precalculated values that are used each round. type Cipher struct { + // table contains a series of precalculated values that are used each round. table [64]uint32 } @@ -54,7 +54,7 @@ func (c *Cipher) BlockSize() int { return BlockSize } // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) } -// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst. +// Decrypt decrypts the 8 byte buffer src using the key and stores the result in dst. func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } // initCipher initializes the cipher context by creating a look up table diff --git a/vendor/golang.org/x/crypto/xts/xts.go b/vendor/golang.org/x/crypto/xts/xts.go index 92cbce9..9654e1f 100644 --- a/vendor/golang.org/x/crypto/xts/xts.go +++ b/vendor/golang.org/x/crypto/xts/xts.go @@ -25,6 +25,8 @@ import ( "crypto/cipher" "encoding/binary" "errors" + + "golang.org/x/crypto/internal/subtle" ) // Cipher contains an expanded key structure. It doesn't contain mutable state @@ -64,6 +66,9 @@ func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { if len(plaintext)%blockSize != 0 { panic("xts: plaintext is not a multiple of the block size") } + if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { + panic("xts: invalid buffer overlap") + } var tweak [blockSize]byte binary.LittleEndian.PutUint64(tweak[:8], sectorNum) @@ -95,6 +100,9 @@ func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { if len(ciphertext)%blockSize != 0 { panic("xts: ciphertext is not a multiple of the block size") } + if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { + panic("xts: invalid buffer overlap") + } var tweak [blockSize]byte binary.LittleEndian.PutUint64(tweak[:8], sectorNum) diff --git a/vendor/golang.org/x/net/CONTRIBUTING.md b/vendor/golang.org/x/net/CONTRIBUTING.md index 88dff59..d0485e8 100644 --- a/vendor/golang.org/x/net/CONTRIBUTING.md +++ b/vendor/golang.org/x/net/CONTRIBUTING.md @@ -4,16 +4,15 @@ Go is an open source project. It is the work of hundreds of contributors. We appreciate your help! - ## Filing issues When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. @@ -23,9 +22,5 @@ The gophers there will answer or ask you to file an issue if you've tripped over Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/net/bpf/instructions.go b/vendor/golang.org/x/net/bpf/instructions.go index 3b4fd08..f9dc0e8 100644 --- a/vendor/golang.org/x/net/bpf/instructions.go +++ b/vendor/golang.org/x/net/bpf/instructions.go @@ -198,7 +198,7 @@ func (a LoadConstant) Assemble() (RawInstruction, error) { return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadConstant) String() string { switch a.Dst { case RegA: @@ -224,7 +224,7 @@ func (a LoadScratch) Assemble() (RawInstruction, error) { return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadScratch) String() string { switch a.Dst { case RegA: @@ -248,7 +248,7 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) { return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadAbsolute) String() string { switch a.Size { case 1: // byte @@ -277,7 +277,7 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) { return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadIndirect) String() string { switch a.Size { case 1: // byte @@ -306,7 +306,7 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) { return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadMemShift) String() string { return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off) } @@ -325,7 +325,7 @@ func (a LoadExtension) Assemble() (RawInstruction, error) { return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadExtension) String() string { switch a.Num { case ExtLen: @@ -392,7 +392,7 @@ func (a StoreScratch) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a StoreScratch) String() string { switch a.Src { case RegA: @@ -418,7 +418,7 @@ func (a ALUOpConstant) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpConstant) String() string { switch a.Op { case ALUOpAdd: @@ -458,7 +458,7 @@ func (a ALUOpX) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpX) String() string { switch a.Op { case ALUOpAdd: @@ -496,7 +496,7 @@ func (a NegateA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a NegateA) String() string { return fmt.Sprintf("neg") } @@ -514,7 +514,7 @@ func (a Jump) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a Jump) String() string { return fmt.Sprintf("ja %d", a.Skip) } @@ -566,7 +566,7 @@ func (a JumpIf) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a JumpIf) String() string { switch a.Cond { // K == A @@ -621,7 +621,7 @@ func (a RetA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetA) String() string { return fmt.Sprintf("ret a") } @@ -639,7 +639,7 @@ func (a RetConstant) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetConstant) String() string { return fmt.Sprintf("ret #%d", a.Val) } @@ -654,7 +654,7 @@ func (a TXA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TXA) String() string { return fmt.Sprintf("txa") } @@ -669,7 +669,7 @@ func (a TAX) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TAX) String() string { return fmt.Sprintf("tax") } diff --git a/vendor/golang.org/x/net/dns/dnsmessage/example_test.go b/vendor/golang.org/x/net/dns/dnsmessage/example_test.go index 5415c2d..8600a6b 100644 --- a/vendor/golang.org/x/net/dns/dnsmessage/example_test.go +++ b/vendor/golang.org/x/net/dns/dnsmessage/example_test.go @@ -37,20 +37,20 @@ func ExampleParser() { }, Answers: []dnsmessage.Resource{ { - dnsmessage.ResourceHeader{ + Header: dnsmessage.ResourceHeader{ Name: mustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, }, - &dnsmessage.AResource{[4]byte{127, 0, 0, 1}}, + Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}, }, { - dnsmessage.ResourceHeader{ + Header: dnsmessage.ResourceHeader{ Name: mustNewName("bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, }, - &dnsmessage.AResource{[4]byte{127, 0, 0, 2}}, + Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}}, }, }, } diff --git a/vendor/golang.org/x/net/dns/dnsmessage/message.go b/vendor/golang.org/x/net/dns/dnsmessage/message.go index ea94bd4..13fbc08 100644 --- a/vendor/golang.org/x/net/dns/dnsmessage/message.go +++ b/vendor/golang.org/x/net/dns/dnsmessage/message.go @@ -5,6 +5,9 @@ // Package dnsmessage provides a mostly RFC 1035 compliant implementation of // DNS message packing and unpacking. // +// The package also supports messages with Extension Mechanisms for DNS +// (EDNS(0)) as defined in RFC 6891. +// // This implementation is designed to minimize heap allocations and avoid // unnecessary packing and unpacking as much as possible. package dnsmessage @@ -18,16 +21,6 @@ import ( // A Type is a type of DNS request and response. type Type uint16 -// A Class is a type of network. -type Class uint16 - -// An OpCode is a DNS operation code. -type OpCode uint16 - -// An RCode is a DNS response status code. -type RCode uint16 - -// Wire constants. const ( // ResourceHeader.Type and Question.Type TypeA Type = 1 @@ -39,6 +32,7 @@ const ( TypeTXT Type = 16 TypeAAAA Type = 28 TypeSRV Type = 33 + TypeOPT Type = 41 // Question.Type TypeWKS Type = 11 @@ -46,7 +40,46 @@ const ( TypeMINFO Type = 14 TypeAXFR Type = 252 TypeALL Type = 255 +) +var typeNames = map[Type]string{ + TypeA: "TypeA", + TypeNS: "TypeNS", + TypeCNAME: "TypeCNAME", + TypeSOA: "TypeSOA", + TypePTR: "TypePTR", + TypeMX: "TypeMX", + TypeTXT: "TypeTXT", + TypeAAAA: "TypeAAAA", + TypeSRV: "TypeSRV", + TypeOPT: "TypeOPT", + TypeWKS: "TypeWKS", + TypeHINFO: "TypeHINFO", + TypeMINFO: "TypeMINFO", + TypeAXFR: "TypeAXFR", + TypeALL: "TypeALL", +} + +// String implements fmt.Stringer.String. +func (t Type) String() string { + if n, ok := typeNames[t]; ok { + return n + } + return printUint16(uint16(t)) +} + +// GoString implements fmt.GoStringer.GoString. +func (t Type) GoString() string { + if n, ok := typeNames[t]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(t)) +} + +// A Class is a type of network. +type Class uint16 + +const ( // ResourceHeader.Class and Question.Class ClassINET Class = 1 ClassCSNET Class = 2 @@ -55,7 +88,44 @@ const ( // Question.Class ClassANY Class = 255 +) +var classNames = map[Class]string{ + ClassINET: "ClassINET", + ClassCSNET: "ClassCSNET", + ClassCHAOS: "ClassCHAOS", + ClassHESIOD: "ClassHESIOD", + ClassANY: "ClassANY", +} + +// String implements fmt.Stringer.String. +func (c Class) String() string { + if n, ok := classNames[c]; ok { + return n + } + return printUint16(uint16(c)) +} + +// GoString implements fmt.GoStringer.GoString. +func (c Class) GoString() string { + if n, ok := classNames[c]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(c)) +} + +// An OpCode is a DNS operation code. +type OpCode uint16 + +// GoString implements fmt.GoStringer.GoString. +func (o OpCode) GoString() string { + return printUint16(uint16(o)) +} + +// An RCode is a DNS response status code. +type RCode uint16 + +const ( // Message.Rcode RCodeSuccess RCode = 0 RCodeFormatError RCode = 1 @@ -65,6 +135,116 @@ const ( RCodeRefused RCode = 5 ) +var rCodeNames = map[RCode]string{ + RCodeSuccess: "RCodeSuccess", + RCodeFormatError: "RCodeFormatError", + RCodeServerFailure: "RCodeServerFailure", + RCodeNameError: "RCodeNameError", + RCodeNotImplemented: "RCodeNotImplemented", + RCodeRefused: "RCodeRefused", +} + +// String implements fmt.Stringer.String. +func (r RCode) String() string { + if n, ok := rCodeNames[r]; ok { + return n + } + return printUint16(uint16(r)) +} + +// GoString implements fmt.GoStringer.GoString. +func (r RCode) GoString() string { + if n, ok := rCodeNames[r]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(r)) +} + +func printPaddedUint8(i uint8) string { + b := byte(i) + return string([]byte{ + b/100 + '0', + b/10%10 + '0', + b%10 + '0', + }) +} + +func printUint8Bytes(buf []byte, i uint8) []byte { + b := byte(i) + if i >= 100 { + buf = append(buf, b/100+'0') + } + if i >= 10 { + buf = append(buf, b/10%10+'0') + } + return append(buf, b%10+'0') +} + +func printByteSlice(b []byte) string { + if len(b) == 0 { + return "" + } + buf := make([]byte, 0, 5*len(b)) + buf = printUint8Bytes(buf, uint8(b[0])) + for _, n := range b[1:] { + buf = append(buf, ',', ' ') + buf = printUint8Bytes(buf, uint8(n)) + } + return string(buf) +} + +const hexDigits = "0123456789abcdef" + +func printString(str []byte) string { + buf := make([]byte, 0, len(str)) + for i := 0; i < len(str); i++ { + c := str[i] + if c == '.' || c == '-' || c == ' ' || + 'A' <= c && c <= 'Z' || + 'a' <= c && c <= 'z' || + '0' <= c && c <= '9' { + buf = append(buf, c) + continue + } + + upper := c >> 4 + lower := (c << 4) >> 4 + buf = append( + buf, + '\\', + 'x', + hexDigits[upper], + hexDigits[lower], + ) + } + return string(buf) +} + +func printUint16(i uint16) string { + return printUint32(uint32(i)) +} + +func printUint32(i uint32) string { + // Max value is 4294967295. + buf := make([]byte, 10) + for b, d := buf, uint32(1000000000); d > 0; d /= 10 { + b[0] = byte(i/d%10 + '0') + if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 { + buf = buf[1:] + } + b = b[1:] + i %= d + } + return string(buf) +} + +func printBool(b bool) string { + if b { + return "true" + } + return "false" +} + var ( // ErrNotStarted indicates that the prerequisite information isn't // available yet because the previous records haven't been appropriately @@ -90,6 +270,8 @@ var ( errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)") errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)") errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)") + errStringTooLong = errors.New("character string exceeds maximum length (255)") + errCompressedSRV = errors.New("compressed name in SRV resource data") ) // Internal constants. @@ -159,6 +341,19 @@ func (m *Header) pack() (id uint16, bits uint16) { return } +// GoString implements fmt.GoStringer.GoString. +func (m *Header) GoString() string { + return "dnsmessage.Header{" + + "ID: " + printUint16(m.ID) + ", " + + "Response: " + printBool(m.Response) + ", " + + "OpCode: " + m.OpCode.GoString() + ", " + + "Authoritative: " + printBool(m.Authoritative) + ", " + + "Truncated: " + printBool(m.Truncated) + ", " + + "RecursionDesired: " + printBool(m.RecursionDesired) + ", " + + "RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " + + "RCode: " + m.RCode.GoString() + "}" +} + // Message is a representation of a DNS message. type Message struct { Header @@ -218,6 +413,7 @@ func (h *header) count(sec section) uint16 { return 0 } +// pack appends the wire format of the header to msg. func (h *header) pack(msg []byte) []byte { msg = packUint16(msg, h.id) msg = packUint16(msg, h.bits) @@ -270,32 +466,43 @@ type Resource struct { Body ResourceBody } +func (r *Resource) GoString() string { + return "dnsmessage.Resource{" + + "Header: " + r.Header.GoString() + + ", Body: &" + r.Body.GoString() + + "}" +} + // A ResourceBody is a DNS resource record minus the header. type ResourceBody interface { // pack packs a Resource except for its header. - pack(msg []byte, compression map[string]int) ([]byte, error) + pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) // realType returns the actual type of the Resource. This is used to // fill in the header Type field. realType() Type + + // GoString implements fmt.GoStringer.GoString. + GoString() string } -func (r *Resource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the Resource to msg. +func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { if r.Body == nil { return msg, errNilResouceBody } oldMsg := msg r.Header.Type = r.Body.realType() - msg, length, err := r.Header.pack(msg, compression) + msg, lenOff, err := r.Header.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"ResourceHeader", err} } preLen := len(msg) - msg, err = r.Body.pack(msg, compression) + msg, err = r.Body.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"content", err} } - if err := r.Header.fixLen(msg, length, preLen); err != nil { + if err := r.Header.fixLen(msg, lenOff, preLen); err != nil { return oldMsg, err } return msg, nil @@ -436,7 +643,13 @@ func (p *Parser) Question() (Question, error) { // AllQuestions parses all Questions. func (p *Parser) AllQuestions() ([]Question, error) { - qs := make([]Question, 0, p.header.questions) + // Multiple questions are valid according to the spec, + // but servers don't actually support them. There will + // be at most one question here. + // + // Do not pre-allocate based on info in p.header, since + // the data is untrusted. + qs := []Question{} for { q, err := p.Question() if err == ErrSectionDone { @@ -492,7 +705,16 @@ func (p *Parser) Answer() (Resource, error) { // AllAnswers parses all Answer Resources. func (p *Parser) AllAnswers() ([]Resource, error) { - as := make([]Resource, 0, p.header.answers) + // The most common query is for A/AAAA, which usually returns + // a handful of IPs. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.answers) + if n > 20 { + n = 20 + } + as := make([]Resource, 0, n) for { a, err := p.Answer() if err == ErrSectionDone { @@ -533,7 +755,16 @@ func (p *Parser) Authority() (Resource, error) { // AllAuthorities parses all Authority Resources. func (p *Parser) AllAuthorities() ([]Resource, error) { - as := make([]Resource, 0, p.header.authorities) + // Authorities contains SOA in case of NXDOMAIN and friends, + // otherwise it is empty. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.authorities) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Authority() if err == ErrSectionDone { @@ -574,7 +805,16 @@ func (p *Parser) Additional() (Resource, error) { // AllAdditionals parses all Additional Resources. func (p *Parser) AllAdditionals() ([]Resource, error) { - as := make([]Resource, 0, p.header.additionals) + // Additionals usually contain OPT, and sometimes A/AAAA + // glue records. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.additionals) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Additional() if err == ErrSectionDone { @@ -765,6 +1005,24 @@ func (p *Parser) AAAAResource() (AAAAResource, error) { return r, nil } +// OPTResource parses a single OPTResource. +// +// One of the XXXHeader methods must have been called before calling this +// method. +func (p *Parser) OPTResource() (OPTResource, error) { + if !p.resHeaderValid || p.resHeader.Type != TypeOPT { + return OPTResource{}, ErrNotStarted + } + r, err := unpackOPTResource(p.msg, p.off, p.resHeader.Length) + if err != nil { + return OPTResource{}, err + } + p.off += int(p.resHeader.Length) + p.resHeaderValid = false + p.index++ + return r, nil +} + // Unpack parses a full Message. func (m *Message) Unpack(msg []byte) error { var p Parser @@ -819,6 +1077,7 @@ func (m *Message) AppendPack(b []byte) ([]byte, error) { h.authorities = uint16(len(m.Authorities)) h.additionals = uint16(len(m.Additionals)) + compressionOff := len(b) msg := h.pack(b) // RFC 1035 allows (but does not require) compression for packing. RFC @@ -833,25 +1092,25 @@ func (m *Message) AppendPack(b []byte) ([]byte, error) { for i := range m.Questions { var err error - if msg, err = m.Questions[i].pack(msg, compression); err != nil { + if msg, err = m.Questions[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Question", err} } } for i := range m.Answers { var err error - if msg, err = m.Answers[i].pack(msg, compression); err != nil { + if msg, err = m.Answers[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Answer", err} } } for i := range m.Authorities { var err error - if msg, err = m.Authorities[i].pack(msg, compression); err != nil { + if msg, err = m.Authorities[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Authority", err} } } for i := range m.Additionals { var err error - if msg, err = m.Additionals[i].pack(msg, compression); err != nil { + if msg, err = m.Additionals[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Additional", err} } } @@ -859,37 +1118,104 @@ func (m *Message) AppendPack(b []byte) ([]byte, error) { return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (m *Message) GoString() string { + s := "dnsmessage.Message{Header: " + m.Header.GoString() + ", " + + "Questions: []dnsmessage.Question{" + if len(m.Questions) > 0 { + s += m.Questions[0].GoString() + for _, q := range m.Questions[1:] { + s += ", " + q.GoString() + } + } + s += "}, Answers: []dnsmessage.Resource{" + if len(m.Answers) > 0 { + s += m.Answers[0].GoString() + for _, a := range m.Answers[1:] { + s += ", " + a.GoString() + } + } + s += "}, Authorities: []dnsmessage.Resource{" + if len(m.Authorities) > 0 { + s += m.Authorities[0].GoString() + for _, a := range m.Authorities[1:] { + s += ", " + a.GoString() + } + } + s += "}, Additionals: []dnsmessage.Resource{" + if len(m.Additionals) > 0 { + s += m.Additionals[0].GoString() + for _, a := range m.Additionals[1:] { + s += ", " + a.GoString() + } + } + return s + "}}" +} + // A Builder allows incrementally packing a DNS message. +// +// Example usage: +// buf := make([]byte, 2, 514) +// b := NewBuilder(buf, Header{...}) +// b.EnableCompression() +// // Optionally start a section and add things to that section. +// // Repeat adding sections as necessary. +// buf, err := b.Finish() +// // If err is nil, buf[2:] will contain the built bytes. type Builder struct { - msg []byte - header header - section section + // msg is the storage for the message being built. + msg []byte + + // section keeps track of the current section being built. + section section + + // header keeps track of what should go in the header when Finish is + // called. + header header + + // start is the starting index of the bytes allocated in msg for header. + start int + + // compression is a mapping from name suffixes to their starting index + // in msg. compression map[string]int } -// Start initializes the builder. +// NewBuilder creates a new builder with compression disabled. // -// buf is optional (nil is fine), but if provided, Start takes ownership of buf. -func (b *Builder) Start(buf []byte, h Header) { - b.StartWithoutCompression(buf, h) - b.compression = map[string]int{} +// Note: Most users will want to immediately enable compression with the +// EnableCompression method. See that method's comment for why you may or may +// not want to enable compression. +// +// The DNS message is appended to the provided initial buffer buf (which may be +// nil) as it is built. The final message is returned by the (*Builder).Finish +// method, which may return the same underlying array if there was sufficient +// capacity in the slice. +func NewBuilder(buf []byte, h Header) Builder { + if buf == nil { + buf = make([]byte, 0, packStartingCap) + } + b := Builder{msg: buf, start: len(buf)} + b.header.id, b.header.bits = h.pack() + var hb [headerLen]byte + b.msg = append(b.msg, hb[:]...) + b.section = sectionHeader + return b } -// StartWithoutCompression initializes the builder with compression disabled. +// EnableCompression enables compression in the Builder. // -// This avoids compression related allocations, but can result in larger message -// sizes. Be careful with this mode as it can cause messages to exceed the UDP -// size limit. +// Leaving compression disabled avoids compression related allocations, but can +// result in larger message sizes. Be careful with this mode as it can cause +// messages to exceed the UDP size limit. // -// buf is optional (nil is fine), but if provided, Start takes ownership of buf. -func (b *Builder) StartWithoutCompression(buf []byte, h Header) { - *b = Builder{msg: buf} - b.header.id, b.header.bits = h.pack() - if cap(b.msg) < headerLen { - b.msg = make([]byte, 0, packStartingCap) - } - b.msg = b.msg[:headerLen] - b.section = sectionHeader +// According to RFC 1035, section 4.1.4, the use of compression is optional, but +// all implementations must accept both compressed and uncompressed DNS +// messages. +// +// Compression should be enabled before any sections are added for best results. +func (b *Builder) EnableCompression() { + b.compression = map[string]int{} } func (b *Builder) startCheck(s section) error { @@ -970,7 +1296,7 @@ func (b *Builder) Question(q Question) error { if b.section > sectionQuestions { return ErrSectionDone } - msg, err := q.pack(b.msg, b.compression) + msg, err := q.pack(b.msg, b.compression, b.start) if err != nil { return err } @@ -997,15 +1323,15 @@ func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"CNAMEResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1021,15 +1347,15 @@ func (b *Builder) MXResource(h ResourceHeader, r MXResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"MXResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1045,15 +1371,15 @@ func (b *Builder) NSResource(h ResourceHeader, r NSResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"NSResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1069,15 +1395,15 @@ func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"PTRResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1093,15 +1419,15 @@ func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"SOAResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1117,15 +1443,15 @@ func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"TXTResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1141,15 +1467,15 @@ func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"SRVResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1165,15 +1491,15 @@ func (b *Builder) AResource(h ResourceHeader, r AResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"AResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1189,15 +1515,39 @@ func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error { return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"AAAAResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { + return err + } + if err := b.incrementSectionCount(); err != nil { + return err + } + b.msg = msg + return nil +} + +// OPTResource adds a single OPTResource. +func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error { + if err := b.checkResourceSection(); err != nil { + return err + } + h.Type = r.realType() + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) + if err != nil { + return &nestedError{"ResourceHeader", err} + } + preLen := len(msg) + if msg, err = r.pack(msg, b.compression, b.start); err != nil { + return &nestedError{"OPTResource body", err} + } + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1213,7 +1563,8 @@ func (b *Builder) Finish() ([]byte, error) { return nil, ErrNotStarted } b.section = sectionDone - b.header.pack(b.msg[:0]) + // Space for the header was allocated in NewBuilder. + b.header.pack(b.msg[b.start:b.start]) return b.msg, nil } @@ -1243,20 +1594,30 @@ type ResourceHeader struct { Length uint16 } -// pack packs all of the fields in a ResourceHeader except for the length. The -// length bytes are returned as a slice so they can be filled in after the rest -// of the Resource has been packed. -func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int) (msg []byte, length []byte, err error) { +// GoString implements fmt.GoStringer.GoString. +func (h *ResourceHeader) GoString() string { + return "dnsmessage.ResourceHeader{" + + "Name: " + h.Name.GoString() + ", " + + "Type: " + h.Type.GoString() + ", " + + "Class: " + h.Class.GoString() + ", " + + "TTL: " + printUint32(h.TTL) + ", " + + "Length: " + printUint16(h.Length) + "}" +} + +// pack appends the wire format of the ResourceHeader to oldMsg. +// +// lenOff is the offset in msg where the Length field was packed. +func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, lenOff int, err error) { msg = oldMsg - if msg, err = h.Name.pack(msg, compression); err != nil { - return oldMsg, nil, &nestedError{"Name", err} + if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil { + return oldMsg, 0, &nestedError{"Name", err} } msg = packType(msg, h.Type) msg = packClass(msg, h.Class) msg = packUint32(msg, h.TTL) - lenBegin := len(msg) + lenOff = len(msg) msg = packUint16(msg, h.Length) - return msg, msg[lenBegin : lenBegin+uint16Len], nil + return msg, lenOff, nil } func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { @@ -1280,19 +1641,63 @@ func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { return newOff, nil } -func (h *ResourceHeader) fixLen(msg []byte, length []byte, preLen int) error { +// fixLen updates a packed ResourceHeader to include the length of the +// ResourceBody. +// +// lenOff is the offset of the ResourceHeader.Length field in msg. +// +// preLen is the length that msg was before the ResourceBody was packed. +func (h *ResourceHeader) fixLen(msg []byte, lenOff int, preLen int) error { conLen := len(msg) - preLen if conLen > int(^uint16(0)) { return errResTooLong } // Fill in the length now that we know how long the content is. - packUint16(length[:0], uint16(conLen)) + packUint16(msg[lenOff:lenOff], uint16(conLen)) h.Length = uint16(conLen) return nil } +// EDNS(0) wire costants. +const ( + edns0Version = 0 + + edns0DNSSECOK = 0x00008000 + ednsVersionMask = 0x00ff0000 + edns0DNSSECOKMask = 0x00ff8000 +) + +// SetEDNS0 configures h for EDNS(0). +// +// The provided extRCode must be an extedned RCode. +func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error { + h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2 + h.Type = TypeOPT + h.Class = Class(udpPayloadLen) + h.TTL = uint32(extRCode) >> 4 << 24 + if dnssecOK { + h.TTL |= edns0DNSSECOK + } + return nil +} + +// DNSSECAllowed reports whether the DNSSEC OK bit is set. +func (h *ResourceHeader) DNSSECAllowed() bool { + return h.TTL&edns0DNSSECOKMask == edns0DNSSECOK // RFC 6891 section 6.1.3 +} + +// ExtendedRCode returns an extended RCode. +// +// The provided rcode must be the RCode in DNS message header. +func (h *ResourceHeader) ExtendedRCode(rcode RCode) RCode { + if h.TTL&ednsVersionMask == edns0Version { // RFC 6891 section 6.1.3 + return RCode(h.TTL>>24<<4) | rcode + } + return rcode +} + func skipResource(msg []byte, off int) (int, error) { newOff, err := skipName(msg, off) if err != nil { @@ -1317,6 +1722,7 @@ func skipResource(msg []byte, off int) (int, error) { return newOff, nil } +// packUint16 appends the wire format of field to msg. func packUint16(msg []byte, field uint16) []byte { return append(msg, byte(field>>8), byte(field)) } @@ -1335,6 +1741,7 @@ func skipUint16(msg []byte, off int) (int, error) { return off + uint16Len, nil } +// packType appends the wire format of field to msg. func packType(msg []byte, field Type) []byte { return packUint16(msg, uint16(field)) } @@ -1348,6 +1755,7 @@ func skipType(msg []byte, off int) (int, error) { return skipUint16(msg, off) } +// packClass appends the wire format of field to msg. func packClass(msg []byte, field Class) []byte { return packUint16(msg, uint16(field)) } @@ -1361,6 +1769,7 @@ func skipClass(msg []byte, off int) (int, error) { return skipUint16(msg, off) } +// packUint32 appends the wire format of field to msg. func packUint32(msg []byte, field uint32) []byte { return append( msg, @@ -1386,17 +1795,16 @@ func skipUint32(msg []byte, off int) (int, error) { return off + uint32Len, nil } -func packText(msg []byte, field string) []byte { - for len(field) > 0 { - l := len(field) - if l > 255 { - l = 255 - } - msg = append(msg, byte(l)) - msg = append(msg, field[:l]...) - field = field[l:] +// packText appends the wire format of field to msg. +func packText(msg []byte, field string) ([]byte, error) { + l := len(field) + if l > 255 { + return nil, errStringTooLong } - return msg + msg = append(msg, byte(l)) + msg = append(msg, field...) + + return msg, nil } func unpackText(msg []byte, off int) (string, int, error) { @@ -1422,6 +1830,7 @@ func skipText(msg []byte, off int) (int, error) { return endOff, nil } +// packBytes appends the wire format of field to msg. func packBytes(msg []byte, field []byte) []byte { return append(msg, field...) } @@ -1462,18 +1871,33 @@ func NewName(name string) (Name, error) { return n, nil } +// MustNewName creates a new Name from a string and panics on error. +func MustNewName(name string) Name { + n, err := NewName(name) + if err != nil { + panic("creating name: " + err.Error()) + } + return n +} + +// String implements fmt.Stringer.String. func (n Name) String() string { return string(n.Data[:n.Length]) } -// pack packs a domain name. +// GoString implements fmt.GoStringer.GoString. +func (n *Name) GoString() string { + return `dnsmessage.MustNewName("` + printString(n.Data[:n.Length]) + `")` +} + +// pack appends the wire format of the Name to msg. // // Domain names are a sequence of counted strings split at the dots. They end // with a zero-length string. Compression can be used to reuse domain suffixes. // // The compression map will be updated with new domain suffixes. If compression // is nil, compression will not be used. -func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) { +func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg // Add a trailing dot to canonicalize name. @@ -1525,7 +1949,7 @@ func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) { // Miss. Add the suffix to the compression table if the // offset can be stored in the available 14 bytes. if len(msg) <= int(^uint16(0)>>2) { - compression[string(n.Data[i:])] = len(msg) + compression[string(n.Data[i:])] = len(msg) - compressionOff } } } @@ -1534,6 +1958,10 @@ func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) { // unpack unpacks a domain name. func (n *Name) unpack(msg []byte, off int) (int, error) { + return n.unpackCompressed(msg, off, true /* allowCompression */) +} + +func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) { // currOff is the current working offset. currOff := off @@ -1569,6 +1997,9 @@ Loop: name = append(name, '.') currOff = endOff case 0xC0: // Pointer + if !allowCompression { + return off, errCompressedSRV + } if currOff >= len(msg) { return off, errInvalidPtr } @@ -1648,8 +2079,9 @@ type Question struct { Class Class } -func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) { - msg, err := q.Name.pack(msg, compression) +// pack appends the wire format of the Question to msg. +func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + msg, err := q.Name.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"Name", err} } @@ -1657,6 +2089,14 @@ func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) return packClass(msg, q.Class), nil } +// GoString implements fmt.GoStringer.GoString. +func (q *Question) GoString() string { + return "dnsmessage.Question{" + + "Name: " + q.Name.GoString() + ", " + + "Type: " + q.Type.GoString() + ", " + + "Class: " + q.Class.GoString() + "}" +} + func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) { var ( r ResourceBody @@ -1709,6 +2149,11 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, rb, err = unpackSRVResource(msg, off) r = &rb name = "SRV" + case TypeOPT: + var rb OPTResource + rb, err = unpackOPTResource(msg, off, hdr.Length) + r = &rb + name = "OPT" } if err != nil { return nil, off, &nestedError{name + " record", err} @@ -1728,8 +2173,14 @@ func (r *CNAMEResource) realType() Type { return TypeCNAME } -func (r *CNAMEResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.CNAME.pack(msg, compression) +// pack appends the wire format of the CNAMEResource to msg. +func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.CNAME.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *CNAMEResource) GoString() string { + return "dnsmessage.CNAMEResource{CNAME: " + r.CNAME.GoString() + "}" } func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) { @@ -1750,16 +2201,24 @@ func (r *MXResource) realType() Type { return TypeMX } -func (r *MXResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the MXResource to msg. +func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg msg = packUint16(msg, r.Pref) - msg, err := r.MX.pack(msg, compression) + msg, err := r.MX.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"MXResource.MX", err} } return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (r *MXResource) GoString() string { + return "dnsmessage.MXResource{" + + "Pref: " + printUint16(r.Pref) + ", " + + "MX: " + r.MX.GoString() + "}" +} + func unpackMXResource(msg []byte, off int) (MXResource, error) { pref, off, err := unpackUint16(msg, off) if err != nil { @@ -1781,8 +2240,14 @@ func (r *NSResource) realType() Type { return TypeNS } -func (r *NSResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.NS.pack(msg, compression) +// pack appends the wire format of the NSResource to msg. +func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.NS.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *NSResource) GoString() string { + return "dnsmessage.NSResource{NS: " + r.NS.GoString() + "}" } func unpackNSResource(msg []byte, off int) (NSResource, error) { @@ -1802,8 +2267,14 @@ func (r *PTRResource) realType() Type { return TypePTR } -func (r *PTRResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.PTR.pack(msg, compression) +// pack appends the wire format of the PTRResource to msg. +func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.PTR.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *PTRResource) GoString() string { + return "dnsmessage.PTRResource{PTR: " + r.PTR.GoString() + "}" } func unpackPTRResource(msg []byte, off int) (PTRResource, error) { @@ -1833,13 +2304,14 @@ func (r *SOAResource) realType() Type { return TypeSOA } -func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the SOAResource to msg. +func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg - msg, err := r.NS.pack(msg, compression) + msg, err := r.NS.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"SOAResource.NS", err} } - msg, err = r.MBox.pack(msg, compression) + msg, err = r.MBox.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"SOAResource.MBox", err} } @@ -1850,6 +2322,18 @@ func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, erro return packUint32(msg, r.MinTTL), nil } +// GoString implements fmt.GoStringer.GoString. +func (r *SOAResource) GoString() string { + return "dnsmessage.SOAResource{" + + "NS: " + r.NS.GoString() + ", " + + "MBox: " + r.MBox.GoString() + ", " + + "Serial: " + printUint32(r.Serial) + ", " + + "Refresh: " + printUint32(r.Refresh) + ", " + + "Retry: " + printUint32(r.Retry) + ", " + + "Expire: " + printUint32(r.Expire) + ", " + + "MinTTL: " + printUint32(r.MinTTL) + "}" +} + func unpackSOAResource(msg []byte, off int) (SOAResource, error) { var ns Name off, err := ns.unpack(msg, off) @@ -1885,19 +2369,41 @@ func unpackSOAResource(msg []byte, off int) (SOAResource, error) { // A TXTResource is a TXT Resource record. type TXTResource struct { - Txt string // Not a domain name. + TXT []string } func (r *TXTResource) realType() Type { return TypeTXT } -func (r *TXTResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packText(msg, r.Txt), nil +// pack appends the wire format of the TXTResource to msg. +func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + oldMsg := msg + for _, s := range r.TXT { + var err error + msg, err = packText(msg, s) + if err != nil { + return oldMsg, err + } + } + return msg, nil +} + +// GoString implements fmt.GoStringer.GoString. +func (r *TXTResource) GoString() string { + s := "dnsmessage.TXTResource{TXT: []string{" + if len(r.TXT) == 0 { + return s + "}}" + } + s += `"` + printString([]byte(r.TXT[0])) + for _, t := range r.TXT[1:] { + s += `", "` + printString([]byte(t)) + } + return s + `"}}` } func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) { - var txt string + txts := make([]string, 0, 1) for n := uint16(0); n < length; { var t string var err error @@ -1909,9 +2415,9 @@ func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) return TXTResource{}, errCalcLen } n += uint16(len(t)) + 1 - txt += t + txts = append(txts, t) } - return TXTResource{txt}, nil + return TXTResource{txts}, nil } // An SRVResource is an SRV Resource record. @@ -1926,18 +2432,28 @@ func (r *SRVResource) realType() Type { return TypeSRV } -func (r *SRVResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the SRVResource to msg. +func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg msg = packUint16(msg, r.Priority) msg = packUint16(msg, r.Weight) msg = packUint16(msg, r.Port) - msg, err := r.Target.pack(msg, nil) + msg, err := r.Target.pack(msg, nil, compressionOff) if err != nil { return oldMsg, &nestedError{"SRVResource.Target", err} } return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (r *SRVResource) GoString() string { + return "dnsmessage.SRVResource{" + + "Priority: " + printUint16(r.Priority) + ", " + + "Weight: " + printUint16(r.Weight) + ", " + + "Port: " + printUint16(r.Port) + ", " + + "Target: " + r.Target.GoString() + "}" +} + func unpackSRVResource(msg []byte, off int) (SRVResource, error) { priority, off, err := unpackUint16(msg, off) if err != nil { @@ -1952,7 +2468,7 @@ func unpackSRVResource(msg []byte, off int) (SRVResource, error) { return SRVResource{}, &nestedError{"Port", err} } var target Name - if _, err := target.unpack(msg, off); err != nil { + if _, err := target.unpackCompressed(msg, off, false /* allowCompression */); err != nil { return SRVResource{}, &nestedError{"Target", err} } return SRVResource{priority, weight, port, target}, nil @@ -1967,10 +2483,17 @@ func (r *AResource) realType() Type { return TypeA } -func (r *AResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the AResource to msg. +func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { return packBytes(msg, r.A[:]), nil } +// GoString implements fmt.GoStringer.GoString. +func (r *AResource) GoString() string { + return "dnsmessage.AResource{" + + "A: [4]byte{" + printByteSlice(r.A[:]) + "}}" +} + func unpackAResource(msg []byte, off int) (AResource, error) { var a [4]byte if _, err := unpackBytes(msg, off, a[:]); err != nil { @@ -1988,7 +2511,14 @@ func (r *AAAAResource) realType() Type { return TypeAAAA } -func (r *AAAAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// GoString implements fmt.GoStringer.GoString. +func (r *AAAAResource) GoString() string { + return "dnsmessage.AAAAResource{" + + "AAAA: [16]byte{" + printByteSlice(r.AAAA[:]) + "}}" +} + +// pack appends the wire format of the AAAAResource to msg. +func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { return packBytes(msg, r.AAAA[:]), nil } @@ -1999,3 +2529,78 @@ func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) { } return AAAAResource{aaaa}, nil } + +// An OPTResource is an OPT pseudo Resource record. +// +// The pseudo resource record is part of the extension mechanisms for DNS +// as defined in RFC 6891. +type OPTResource struct { + Options []Option +} + +// An Option represents a DNS message option within OPTResource. +// +// The message option is part of the extension mechanisms for DNS as +// defined in RFC 6891. +type Option struct { + Code uint16 // option code + Data []byte +} + +// GoString implements fmt.GoStringer.GoString. +func (o *Option) GoString() string { + return "dnsmessage.Option{" + + "Code: " + printUint16(o.Code) + ", " + + "Data: []byte{" + printByteSlice(o.Data) + "}}" +} + +func (r *OPTResource) realType() Type { + return TypeOPT +} + +func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + for _, opt := range r.Options { + msg = packUint16(msg, opt.Code) + l := uint16(len(opt.Data)) + msg = packUint16(msg, l) + msg = packBytes(msg, opt.Data) + } + return msg, nil +} + +// GoString implements fmt.GoStringer.GoString. +func (r *OPTResource) GoString() string { + s := "dnsmessage.OPTResource{Options: []dnsmessage.Option{" + if len(r.Options) == 0 { + return s + "}}" + } + s += r.Options[0].GoString() + for _, o := range r.Options[1:] { + s += ", " + o.GoString() + } + return s + "}}" +} + +func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) { + var opts []Option + for oldOff := off; off < oldOff+int(length); { + var err error + var o Option + o.Code, off, err = unpackUint16(msg, off) + if err != nil { + return OPTResource{}, &nestedError{"Code", err} + } + var l uint16 + l, off, err = unpackUint16(msg, off) + if err != nil { + return OPTResource{}, &nestedError{"Data", err} + } + o.Data = make([]byte, l) + if copy(o.Data, msg[off:]) != int(l) { + return OPTResource{}, &nestedError{"Data", errCalcLen} + } + off += int(l) + opts = append(opts, o) + } + return OPTResource{opts}, nil +} diff --git a/vendor/golang.org/x/net/dns/dnsmessage/message_test.go b/vendor/golang.org/x/net/dns/dnsmessage/message_test.go index 2bb7634..25ba8f0 100644 --- a/vendor/golang.org/x/net/dns/dnsmessage/message_test.go +++ b/vendor/golang.org/x/net/dns/dnsmessage/message_test.go @@ -8,15 +8,109 @@ import ( "bytes" "fmt" "reflect" + "strings" "testing" ) -func mustNewName(name string) Name { - n, err := NewName(name) - if err != nil { +func TestPrintPaddedUint8(t *testing.T) { + tests := []struct { + num uint8 + want string + }{ + {0, "000"}, + {1, "001"}, + {9, "009"}, + {10, "010"}, + {99, "099"}, + {100, "100"}, + {124, "124"}, + {104, "104"}, + {120, "120"}, + {255, "255"}, + } + + for _, test := range tests { + if got := printPaddedUint8(test.num); got != test.want { + t.Errorf("got printPaddedUint8(%d) = %s, want = %s", test.num, got, test.want) + } + } +} + +func TestPrintUint8Bytes(t *testing.T) { + tests := []uint8{ + 0, + 1, + 9, + 10, + 99, + 100, + 124, + 104, + 120, + 255, + } + + for _, test := range tests { + if got, want := string(printUint8Bytes(nil, test)), fmt.Sprint(test); got != want { + t.Errorf("got printUint8Bytes(%d) = %s, want = %s", test, got, want) + } + } +} + +func TestPrintUint16(t *testing.T) { + tests := []uint16{ + 65535, + 0, + 1, + 10, + 100, + 1000, + 10000, + 324, + 304, + 320, + } + + for _, test := range tests { + if got, want := printUint16(test), fmt.Sprint(test); got != want { + t.Errorf("got printUint16(%d) = %s, want = %s", test, got, want) + } + } +} + +func TestPrintUint32(t *testing.T) { + tests := []uint32{ + 4294967295, + 65535, + 0, + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 324, + 304, + 320, + } + + for _, test := range tests { + if got, want := printUint32(test), fmt.Sprint(test); got != want { + t.Errorf("got printUint32(%d) = %s, want = %s", test, got, want) + } + } +} + +func mustEDNS0ResourceHeader(l int, extrc RCode, do bool) ResourceHeader { + h := ResourceHeader{Class: ClassINET} + if err := h.SetEDNS0(l, extrc, do); err != nil { panic(err) } - return n + return h } func (m *Message) String() string { @@ -50,7 +144,7 @@ func (m *Message) String() string { func TestNameString(t *testing.T) { want := "foo" - name := mustNewName(want) + name := MustNewName(want) if got := fmt.Sprint(name); got != want { t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want) } @@ -58,13 +152,13 @@ func TestNameString(t *testing.T) { func TestQuestionPackUnpack(t *testing.T) { want := Question{ - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeA, Class: ClassINET, } - buf, err := want.pack(make([]byte, 1, 50), map[string]int{}) + buf, err := want.pack(make([]byte, 1, 50), map[string]int{}, 1) if err != nil { - t.Fatal("Packing failed:", err) + t.Fatal("Question.pack() =", err) } var p Parser p.msg = buf @@ -73,13 +167,13 @@ func TestQuestionPackUnpack(t *testing.T) { p.off = 1 got, err := p.Question() if err != nil { - t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:])) + t.Fatalf("Parser{%q}.Question() = %v", string(buf[1:]), err) } if p.off != len(buf) { - t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf)) + t.Errorf("unpacked different amount than packed: got = %d, want = %d", p.off, len(buf)) } if !reflect.DeepEqual(got, want) { - t.Errorf("Got = %+v, want = %+v", got, want) + t.Errorf("got from Parser.Question() = %+v, want = %+v", got, want) } } @@ -99,11 +193,11 @@ func TestName(t *testing.T) { for _, test := range tests { n, err := NewName(test) if err != nil { - t.Errorf("Creating name for %q: %v", test, err) + t.Errorf("NewName(%q) = %v", test, err) continue } if ns := n.String(); ns != test { - t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test) + t.Errorf("got %#v.String() = %q, want = %q", n, ns, test) continue } } @@ -127,11 +221,11 @@ func TestNamePackUnpack(t *testing.T) { } for _, test := range tests { - in := mustNewName(test.in) - want := mustNewName(test.want) - buf, err := in.pack(make([]byte, 0, 30), map[string]int{}) + in := MustNewName(test.in) + want := MustNewName(test.want) + buf, err := in.pack(make([]byte, 0, 30), map[string]int{}, 0) if err != test.err { - t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err) + t.Errorf("got %q.pack() = %v, want = %v", test.in, err, test.err) continue } if test.err != nil { @@ -140,23 +234,45 @@ func TestNamePackUnpack(t *testing.T) { var got Name n, err := got.unpack(buf, 0) if err != nil { - t.Errorf("Unpacking for %q failed: %v", test.in, err) + t.Errorf("%q.unpack() = %v", test.in, err) continue } if n != len(buf) { t.Errorf( - "Unpacked different amount than packed for %q: got n = %d, want = %d", + "unpacked different amount than packed for %q: got = %d, want = %d", test.in, n, len(buf), ) } if got != want { - t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want) + t.Errorf("unpacking packing of %q: got = %#v, want = %#v", test.in, got, want) } } } +func TestIncompressibleName(t *testing.T) { + name := MustNewName("example.com.") + compression := map[string]int{} + buf, err := name.pack(make([]byte, 0, 100), compression, 0) + if err != nil { + t.Fatal("first Name.pack() =", err) + } + buf, err = name.pack(buf, compression, 0) + if err != nil { + t.Fatal("second Name.pack() =", err) + } + var n1 Name + off, err := n1.unpackCompressed(buf, 0, false /* allowCompression */) + if err != nil { + t.Fatal("unpacking incompressible name without pointers failed:", err) + } + var n2 Name + if _, err := n2.unpackCompressed(buf, off, false /* allowCompression */); err != errCompressedSRV { + t.Errorf("unpacking compressed incompressible name with pointers: got %v, want = %v", err, errCompressedSRV) + } +} + func checkErrorPrefix(err error, prefix string) bool { e, ok := err.(*nestedError) return ok && e.s == prefix @@ -176,7 +292,7 @@ func TestHeaderUnpackError(t *testing.T) { for _, want := range wants { n, err := h.unpack(buf, 0) if n != 0 || !checkErrorPrefix(err, want) { - t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want) + t.Errorf("got header.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want) } buf = append(buf, 0, 0) } @@ -188,7 +304,7 @@ func TestParserStart(t *testing.T) { for i := 0; i <= 1; i++ { _, err := p.Start([]byte{}) if !checkErrorPrefix(err, want) { - t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want) + t.Errorf("got Parser.Start(nil) = _, %v, want = _, %s", err, want) } } } @@ -211,7 +327,7 @@ func TestResourceNotStarted(t *testing.T) { for _, test := range tests { if err := test.fn(&Parser{}); err != ErrNotStarted { - t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted) + t.Errorf("got Parser.%s() = _ , %v, want = _, %v", test.name, err, ErrNotStarted) } } } @@ -221,7 +337,7 @@ func TestDNSPackUnpack(t *testing.T) { { Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -235,15 +351,49 @@ func TestDNSPackUnpack(t *testing.T) { for i, want := range wants { b, err := want.Pack() if err != nil { - t.Fatalf("%d: packing failed: %v", i, err) + t.Fatalf("%d: Message.Pack() = %v", i, err) } var got Message err = got.Unpack(b) if err != nil { - t.Fatalf("%d: unpacking failed: %v", i, err) + t.Fatalf("%d: Message.Unapck() = %v", i, err) } if !reflect.DeepEqual(got, want) { - t.Errorf("%d: got = %+v, want = %+v", i, &got, &want) + t.Errorf("%d: Message.Pack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want) + } + } +} + +func TestDNSAppendPackUnpack(t *testing.T) { + wants := []Message{ + { + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Answers: []Resource{}, + Authorities: []Resource{}, + Additionals: []Resource{}, + }, + largeTestMsg(), + } + for i, want := range wants { + b := make([]byte, 2, 514) + b, err := want.AppendPack(b) + if err != nil { + t.Fatalf("%d: Message.AppendPack() = %v", i, err) + } + b = b[2:] + var got Message + err = got.Unpack(b) + if err != nil { + t.Fatalf("%d: Message.Unapck() = %v", i, err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("%d: Message.AppendPack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want) } } } @@ -252,11 +402,11 @@ func TestSkipAll(t *testing.T) { msg := largeTestMsg() buf, err := msg.Pack() if err != nil { - t.Fatal("Packing large test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Start(non-nil) =", err) } tests := []struct { @@ -271,7 +421,7 @@ func TestSkipAll(t *testing.T) { for _, test := range tests { for i := 1; i <= 3; i++ { if err := test.f(); err != nil { - t.Errorf("Call #%d to %s(): %v", i, test.name, err) + t.Errorf("%d: Parser.%s() = %v", i, test.name, err) } } } @@ -282,11 +432,11 @@ func TestSkipEach(t *testing.T) { buf, err := msg.Pack() if err != nil { - t.Fatal("Packing test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Start(non-nil) =", err) } tests := []struct { @@ -300,10 +450,10 @@ func TestSkipEach(t *testing.T) { } for _, test := range tests { if err := test.f(); err != nil { - t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil) + t.Errorf("first Parser.%s() = %v, want = nil", test.name, err) } if err := test.f(); err != ErrSectionDone { - t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone) + t.Errorf("second Parser.%s() = %v, want = %v", test.name, err, ErrSectionDone) } } } @@ -313,11 +463,11 @@ func TestSkipAfterRead(t *testing.T) { buf, err := msg.Pack() if err != nil { - t.Fatal("Packing test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Srart(non-nil) =", err) } tests := []struct { @@ -332,10 +482,10 @@ func TestSkipAfterRead(t *testing.T) { } for _, test := range tests { if err := test.read(); err != nil { - t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil) + t.Errorf("got Parser.%s() = _, %v, want = _, nil", test.name, err) } if err := test.skip(); err != ErrSectionDone { - t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone) + t.Errorf("got Parser.Skip%s() = %v, want = %v", test.name, err, ErrSectionDone) } } } @@ -354,7 +504,7 @@ func TestSkipNotStarted(t *testing.T) { } for _, test := range tests { if err := test.f(); err != ErrNotStarted { - t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted) + t.Errorf("got Parser.%s() = %v, want = %v", test.name, err, ErrNotStarted) } } } @@ -398,7 +548,7 @@ func TestTooManyRecords(t *testing.T) { for _, test := range tests { if _, got := test.msg.Pack(); got != test.want { - t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want) + t.Errorf("got Message.Pack() for %d %s = %v, want = %v", recs, test.name, got, test.want) } } } @@ -406,31 +556,66 @@ func TestTooManyRecords(t *testing.T) { func TestVeryLongTxt(t *testing.T) { want := Resource{ ResourceHeader{ - Name: mustNewName("foo.bar.example.com."), + Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, }, - &TXTResource{loremIpsum}, + &TXTResource{[]string{ + "", + "", + "foo bar", + "", + "www.example.com", + "www.example.com.", + strings.Repeat(".", 255), + }}, } - buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}) + buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0) if err != nil { - t.Fatal("Packing failed:", err) + t.Fatal("Resource.pack() =", err) } var got Resource off, err := got.Header.unpack(buf, 0) if err != nil { - t.Fatal("Unpacking ResourceHeader failed:", err) + t.Fatal("ResourceHeader.unpack() =", err) } body, n, err := unpackResourceBody(buf, off, got.Header) if err != nil { - t.Fatal("Unpacking failed:", err) + t.Fatal("unpackResourceBody() =", err) } got.Body = body if n != len(buf) { - t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf)) + t.Errorf("unpacked different amount than packed: got = %d, want = %d", n, len(buf)) } if !reflect.DeepEqual(got, want) { - t.Errorf("Got = %#v, want = %#v", got, want) + t.Errorf("Resource.pack/unpack() roundtrip: got = %#v, want = %#v", got, want) + } +} + +func TestTooLongTxt(t *testing.T) { + rb := TXTResource{[]string{strings.Repeat(".", 256)}} + if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong { + t.Errorf("packing TXTResource with 256 character string: got err = %v, want = %v", err, errStringTooLong) + } +} + +func TestStartAppends(t *testing.T) { + buf := make([]byte, 2, 514) + wantBuf := []byte{4, 44} + copy(buf, wantBuf) + + b := NewBuilder(buf, Header{}) + b.EnableCompression() + + buf, err := b.Finish() + if err != nil { + t.Fatal("Builder.Finish() =", err) + } + if got, want := len(buf), headerLen+2; got != want { + t.Errorf("got len(buf) = %d, want = %d", got, want) + } + if string(buf[:2]) != string(wantBuf) { + t.Errorf("original data not preserved, got = %#v, want = %#v", buf[:2], wantBuf) } } @@ -457,7 +642,7 @@ func TestStartError(t *testing.T) { for _, env := range envs { for _, test := range tests { if got := test.fn(env.fn()); got != env.want { - t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want) + t.Errorf("got Builder{%s}.Start%s() = %v, want = %v", env.name, test.name, got, env.want) } } } @@ -477,6 +662,7 @@ func TestBuilderResourceError(t *testing.T) { {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }}, {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }}, {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }}, + {"OPTResource", func(b *Builder) error { return b.OPTResource(ResourceHeader{}, OPTResource{}) }}, } envs := []struct { @@ -493,7 +679,7 @@ func TestBuilderResourceError(t *testing.T) { for _, env := range envs { for _, test := range tests { if got := test.fn(env.fn()); got != env.want { - t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want) + t.Errorf("got Builder{%s}.%s() = %v, want = %v", env.name, test.name, got, env.want) } } } @@ -503,7 +689,7 @@ func TestFinishError(t *testing.T) { var b Builder want := ErrNotStarted if _, got := b.Finish(); got != want { - t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want) + t.Errorf("got Builder.Finish() = %v, want = %v", got, want) } } @@ -511,89 +697,96 @@ func TestBuilder(t *testing.T) { msg := largeTestMsg() want, err := msg.Pack() if err != nil { - t.Fatal("Packing without builder:", err) + t.Fatal("Message.Pack() =", err) } - var b Builder - b.Start(nil, msg.Header) + b := NewBuilder(nil, msg.Header) + b.EnableCompression() if err := b.StartQuestions(); err != nil { - t.Fatal("b.StartQuestions():", err) + t.Fatal("Builder.StartQuestions() =", err) } for _, q := range msg.Questions { if err := b.Question(q); err != nil { - t.Fatalf("b.Question(%#v): %v", q, err) + t.Fatalf("Builder.Question(%#v) = %v", q, err) } } if err := b.StartAnswers(); err != nil { - t.Fatal("b.StartAnswers():", err) + t.Fatal("Builder.StartAnswers() =", err) } for _, a := range msg.Answers { switch a.Header.Type { case TypeA: if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil { - t.Fatalf("b.AResource(%#v): %v", a, err) + t.Fatalf("Builder.AResource(%#v) = %v", a, err) } case TypeNS: if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil { - t.Fatalf("b.NSResource(%#v): %v", a, err) + t.Fatalf("Builder.NSResource(%#v) = %v", a, err) } case TypeCNAME: if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil { - t.Fatalf("b.CNAMEResource(%#v): %v", a, err) + t.Fatalf("Builder.CNAMEResource(%#v) = %v", a, err) } case TypeSOA: if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil { - t.Fatalf("b.SOAResource(%#v): %v", a, err) + t.Fatalf("Builder.SOAResource(%#v) = %v", a, err) } case TypePTR: if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil { - t.Fatalf("b.PTRResource(%#v): %v", a, err) + t.Fatalf("Builder.PTRResource(%#v) = %v", a, err) } case TypeMX: if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil { - t.Fatalf("b.MXResource(%#v): %v", a, err) + t.Fatalf("Builder.MXResource(%#v) = %v", a, err) } case TypeTXT: if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { - t.Fatalf("b.TXTResource(%#v): %v", a, err) + t.Fatalf("Builder.TXTResource(%#v) = %v", a, err) } case TypeAAAA: if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil { - t.Fatalf("b.AAAAResource(%#v): %v", a, err) + t.Fatalf("Builder.AAAAResource(%#v) = %v", a, err) } case TypeSRV: if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil { - t.Fatalf("b.SRVResource(%#v): %v", a, err) + t.Fatalf("Builder.SRVResource(%#v) = %v", a, err) } } } if err := b.StartAuthorities(); err != nil { - t.Fatal("b.StartAuthorities():", err) + t.Fatal("Builder.StartAuthorities() =", err) } for _, a := range msg.Authorities { if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil { - t.Fatalf("b.NSResource(%#v): %v", a, err) + t.Fatalf("Builder.NSResource(%#v) = %v", a, err) } } if err := b.StartAdditionals(); err != nil { - t.Fatal("b.StartAdditionals():", err) + t.Fatal("Builder.StartAdditionals() =", err) } for _, a := range msg.Additionals { - if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { - t.Fatalf("b.TXTResource(%#v): %v", a, err) + switch a.Body.(type) { + case *TXTResource: + if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { + t.Fatalf("Builder.TXTResource(%#v) = %v", a, err) + } + case *OPTResource: + if err := b.OPTResource(a.Header, *a.Body.(*OPTResource)); err != nil { + t.Fatalf("Builder.OPTResource(%#v) = %v", a, err) + } } } got, err := b.Finish() if err != nil { - t.Fatal("b.Finish():", err) + t.Fatal("Builder.Finish() =", err) } if !bytes.Equal(got, want) { - t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want) + t.Fatalf("got from Builder.Finish() = %#v\nwant = %#v", got, want) } } @@ -606,7 +799,7 @@ func TestResourcePack(t *testing.T) { Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -619,7 +812,7 @@ func TestResourcePack(t *testing.T) { Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -636,7 +829,7 @@ func TestResourcePack(t *testing.T) { Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeA, Class: ClassINET, }, @@ -648,15 +841,202 @@ func TestResourcePack(t *testing.T) { } { _, err := tt.m.Pack() if !reflect.DeepEqual(err, tt.err) { - t.Errorf("got %v for %v; want %v", err, tt.m, tt.err) + t.Errorf("got Message{%v}.Pack() = %v, want %v", tt.m, err, tt.err) } } } -func BenchmarkParsing(b *testing.B) { - b.ReportAllocs() +func TestResourcePackLength(t *testing.T) { + r := Resource{ + ResourceHeader{ + Name: MustNewName("."), + Type: TypeA, + Class: ClassINET, + }, + &AResource{[4]byte{127, 0, 0, 2}}, + } - name := mustNewName("foo.bar.example.com.") + hb, _, err := r.Header.pack(nil, nil, 0) + if err != nil { + t.Fatal("ResourceHeader.pack() =", err) + } + buf := make([]byte, 0, len(hb)) + buf, err = r.pack(buf, nil, 0) + if err != nil { + t.Fatal("Resource.pack() =", err) + } + + var hdr ResourceHeader + if _, err := hdr.unpack(buf, 0); err != nil { + t.Fatal("ResourceHeader.unpack() =", err) + } + + if got, want := int(hdr.Length), len(buf)-len(hb); got != want { + t.Errorf("got hdr.Length = %d, want = %d", got, want) + } +} + +func TestOptionPackUnpack(t *testing.T) { + for _, tt := range []struct { + name string + w []byte // wire format of m.Additionals + m Message + dnssecOK bool + extRCode RCode + }{ + { + name: "without EDNS(0) options", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xfe, 0x00, 0x80, + 0x00, 0x00, 0x00, + }, + m: Message{ + Header: Header{RCode: RCodeFormatError}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xfe0|RCodeFormatError, true), + &OPTResource{}, + }, + }, + }, + dnssecOK: true, + extRCode: 0xfe0 | RCodeFormatError, + }, + { + name: "with EDNS(0) options", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x02, 0x12, 0x34, + }, + m: Message{ + Header: Header{RCode: RCodeServerFailure}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeServerFailure, false), + &OPTResource{ + Options: []Option{ + { + Code: 12, // see RFC 7828 + Data: []byte{0x00, 0x00}, + }, + { + Code: 11, // see RFC 7830 + Data: []byte{0x12, 0x34}, + }, + }, + }, + }, + }, + }, + dnssecOK: false, + extRCode: 0xff0 | RCodeServerFailure, + }, + { + // Containing multiple OPT resources in a + // message is invalid, but it's necessary for + // protocol conformance testing. + name: "with multiple OPT resources", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x02, 0x12, + 0x34, 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x02, + 0x00, 0x00, + }, + m: Message{ + Header: Header{RCode: RCodeNameError}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false), + &OPTResource{ + Options: []Option{ + { + Code: 11, // see RFC 7830 + Data: []byte{0x12, 0x34}, + }, + }, + }, + }, + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false), + &OPTResource{ + Options: []Option{ + { + Code: 12, // see RFC 7828 + Data: []byte{0x00, 0x00}, + }, + }, + }, + }, + }, + }, + }, + } { + w, err := tt.m.Pack() + if err != nil { + t.Errorf("Message.Pack() for %s = %v", tt.name, err) + continue + } + if !bytes.Equal(w[len(w)-len(tt.w):], tt.w) { + t.Errorf("got Message.Pack() for %s = %#v, want %#v", tt.name, w[len(w)-len(tt.w):], tt.w) + continue + } + var m Message + if err := m.Unpack(w); err != nil { + t.Errorf("Message.Unpack() for %s = %v", tt.name, err) + continue + } + if !reflect.DeepEqual(m.Additionals, tt.m.Additionals) { + t.Errorf("got Message.Pack/Unpack() roundtrip for %s = %+v, want %+v", tt.name, m, tt.m) + continue + } + } +} + +// TestGoString tests that Message.GoString produces Go code that compiles to +// reproduce the Message. +// +// This test was produced as follows: +// 1. Run (*Message).GoString on largeTestMsg(). +// 2. Remove "dnsmessage." from the output. +// 3. Paste the result in the test to store it in msg. +// 4. Also put the original output in the test to store in want. +func TestGoString(t *testing.T) { + msg := Message{Header: Header{ID: 0, Response: true, OpCode: 0, Authoritative: true, Truncated: false, RecursionDesired: false, RecursionAvailable: false, RCode: RCodeSuccess}, Questions: []Question{{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET}}, Answers: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AResource{A: [4]byte{127, 0, 0, 1}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AResource{A: [4]byte{127, 0, 0, 2}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeAAAA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AAAAResource{AAAA: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeCNAME, Class: ClassINET, TTL: 0, Length: 0}, Body: &CNAMEResource{CNAME: MustNewName("alias.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeSOA, Class: ClassINET, TTL: 0, Length: 0}, Body: &SOAResource{NS: MustNewName("ns1.example.com."), MBox: MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, Expire: 4, MinTTL: 5}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypePTR, Class: ClassINET, TTL: 0, Length: 0}, Body: &PTRResource{PTR: MustNewName("ptr.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeMX, Class: ClassINET, TTL: 0, Length: 0}, Body: &MXResource{Pref: 7, MX: MustNewName("mx.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeSRV, Class: ClassINET, TTL: 0, Length: 0}, Body: &SRVResource{Priority: 8, Weight: 9, Port: 11, Target: MustNewName("srv.example.com.")}}}, Authorities: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeNS, Class: ClassINET, TTL: 0, Length: 0}, Body: &NSResource{NS: MustNewName("ns1.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeNS, Class: ClassINET, TTL: 0, Length: 0}, Body: &NSResource{NS: MustNewName("ns2.example.com.")}}}, Additionals: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, TTL: 0, Length: 0}, Body: &TXTResource{TXT: []string{"So Long\x2c and Thanks for All the Fish"}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, TTL: 0, Length: 0}, Body: &TXTResource{TXT: []string{"Hamster Huey and the Gooey Kablooie"}}}, {Header: ResourceHeader{Name: MustNewName("."), Type: TypeOPT, Class: 4096, TTL: 4261412864, Length: 0}, Body: &OPTResource{Options: []Option{{Code: 10, Data: []byte{1, 35, 69, 103, 137, 171, 205, 239}}}}}}} + if !reflect.DeepEqual(msg, largeTestMsg()) { + t.Error("Message.GoString lost information or largeTestMsg changed: msg != largeTestMsg()") + } + got := msg.GoString() + want := `dnsmessage.Message{Header: dnsmessage.Header{ID: 0, Response: true, OpCode: 0, Authoritative: true, Truncated: false, RecursionDesired: false, RecursionAvailable: false, RCode: dnsmessage.RCodeSuccess}, Questions: []dnsmessage.Question{dnsmessage.Question{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET}}, Answers: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeAAAA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AAAAResource{AAAA: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeCNAME, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.CNAMEResource{CNAME: dnsmessage.MustNewName("alias.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeSOA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.SOAResource{NS: dnsmessage.MustNewName("ns1.example.com."), MBox: dnsmessage.MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, Expire: 4, MinTTL: 5}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypePTR, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.PTRResource{PTR: dnsmessage.MustNewName("ptr.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeMX, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.MXResource{Pref: 7, MX: dnsmessage.MustNewName("mx.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeSRV, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.SRVResource{Priority: 8, Weight: 9, Port: 11, Target: dnsmessage.MustNewName("srv.example.com.")}}}, Authorities: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeNS, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.NSResource{NS: dnsmessage.MustNewName("ns1.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeNS, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.NSResource{NS: dnsmessage.MustNewName("ns2.example.com.")}}}, Additionals: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeTXT, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.TXTResource{TXT: []string{"So Long\x2c and Thanks for All the Fish"}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeTXT, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.TXTResource{TXT: []string{"Hamster Huey and the Gooey Kablooie"}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("."), Type: dnsmessage.TypeOPT, Class: 4096, TTL: 4261412864, Length: 0}, Body: &dnsmessage.OPTResource{Options: []dnsmessage.Option{dnsmessage.Option{Code: 10, Data: []byte{1, 35, 69, 103, 137, 171, 205, 239}}}}}}}` + if got != want { + t.Errorf("got msg1.GoString() = %s\nwant = %s", got, want) + } +} + +func benchmarkParsingSetup() ([]byte, error) { + name := MustNewName("foo.bar.example.com.") msg := Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -700,116 +1080,166 @@ func BenchmarkParsing(b *testing.B) { buf, err := msg.Pack() if err != nil { - b.Fatal("msg.Pack():", err) + return nil, fmt.Errorf("Message.Pack() = %v", err) + } + return buf, nil +} + +func benchmarkParsing(tb testing.TB, buf []byte) { + var p Parser + if _, err := p.Start(buf); err != nil { + tb.Fatal("Parser.Start(non-nil) =", err) } + for { + _, err := p.Question() + if err == ErrSectionDone { + break + } + if err != nil { + tb.Fatal("Parser.Question() =", err) + } + } + + for { + h, err := p.AnswerHeader() + if err == ErrSectionDone { + break + } + if err != nil { + tb.Fatal("Parser.AnswerHeader() =", err) + } + + switch h.Type { + case TypeA: + if _, err := p.AResource(); err != nil { + tb.Fatal("Parser.AResource() =", err) + } + case TypeAAAA: + if _, err := p.AAAAResource(); err != nil { + tb.Fatal("Parser.AAAAResource() =", err) + } + case TypeCNAME: + if _, err := p.CNAMEResource(); err != nil { + tb.Fatal("Parser.CNAMEResource() =", err) + } + case TypeNS: + if _, err := p.NSResource(); err != nil { + tb.Fatal("Parser.NSResource() =", err) + } + case TypeOPT: + if _, err := p.OPTResource(); err != nil { + tb.Fatal("Parser.OPTResource() =", err) + } + default: + tb.Fatalf("got unknown type: %T", h) + } + } +} + +func BenchmarkParsing(b *testing.B) { + buf, err := benchmarkParsingSetup() + if err != nil { + b.Fatal(err) + } + + b.ReportAllocs() for i := 0; i < b.N; i++ { - var p Parser - if _, err := p.Start(buf); err != nil { - b.Fatal("p.Start(buf):", err) - } + benchmarkParsing(b, buf) + } +} - for { - _, err := p.Question() - if err == ErrSectionDone { - break - } - if err != nil { - b.Fatal("p.Question():", err) - } - } +func TestParsingAllocs(t *testing.T) { + buf, err := benchmarkParsingSetup() + if err != nil { + t.Fatal(err) + } - for { - h, err := p.AnswerHeader() - if err == ErrSectionDone { - break - } - if err != nil { - panic(err) - } + if allocs := testing.AllocsPerRun(100, func() { benchmarkParsing(t, buf) }); allocs > 0.5 { + t.Errorf("allocations during parsing: got = %f, want ~0", allocs) + } +} - switch h.Type { - case TypeA: - if _, err := p.AResource(); err != nil { - b.Fatal("p.AResource():", err) - } - case TypeAAAA: - if _, err := p.AAAAResource(); err != nil { - b.Fatal("p.AAAAResource():", err) - } - case TypeCNAME: - if _, err := p.CNAMEResource(); err != nil { - b.Fatal("p.CNAMEResource():", err) - } - case TypeNS: - if _, err := p.NSResource(); err != nil { - b.Fatal("p.NSResource():", err) - } - default: - b.Fatalf("unknown type: %T", h) - } - } +func benchmarkBuildingSetup() (Name, []byte) { + name := MustNewName("foo.bar.example.com.") + buf := make([]byte, 0, packStartingCap) + return name, buf +} + +func benchmarkBuilding(tb testing.TB, name Name, buf []byte) { + bld := NewBuilder(buf, Header{Response: true, Authoritative: true}) + + if err := bld.StartQuestions(); err != nil { + tb.Fatal("Builder.StartQuestions() =", err) + } + q := Question{ + Name: name, + Type: TypeA, + Class: ClassINET, + } + if err := bld.Question(q); err != nil { + tb.Fatalf("Builder.Question(%+v) = %v", q, err) + } + + hdr := ResourceHeader{ + Name: name, + Class: ClassINET, + } + if err := bld.StartAnswers(); err != nil { + tb.Fatal("Builder.StartQuestions() =", err) + } + + ar := AResource{[4]byte{}} + if err := bld.AResource(hdr, ar); err != nil { + tb.Fatalf("Builder.AResource(%+v, %+v) = %v", hdr, ar, err) + } + + aaar := AAAAResource{[16]byte{}} + if err := bld.AAAAResource(hdr, aaar); err != nil { + tb.Fatalf("Builder.AAAAResource(%+v, %+v) = %v", hdr, aaar, err) + } + + cnr := CNAMEResource{name} + if err := bld.CNAMEResource(hdr, cnr); err != nil { + tb.Fatalf("Builder.CNAMEResource(%+v, %+v) = %v", hdr, cnr, err) + } + + nsr := NSResource{name} + if err := bld.NSResource(hdr, nsr); err != nil { + tb.Fatalf("Builder.NSResource(%+v, %+v) = %v", hdr, nsr, err) + } + + extrc := 0xfe0 | RCodeNotImplemented + if err := (&hdr).SetEDNS0(4096, extrc, true); err != nil { + tb.Fatalf("ResourceHeader.SetEDNS0(4096, %#x, true) = %v", extrc, err) + } + optr := OPTResource{} + if err := bld.OPTResource(hdr, optr); err != nil { + tb.Fatalf("Builder.OPTResource(%+v, %+v) = %v", hdr, optr, err) + } + + if _, err := bld.Finish(); err != nil { + tb.Fatal("Builder.Finish() =", err) } } func BenchmarkBuilding(b *testing.B) { + name, buf := benchmarkBuildingSetup() b.ReportAllocs() - - name := mustNewName("foo.bar.example.com.") - buf := make([]byte, 0, packStartingCap) - for i := 0; i < b.N; i++ { - var bld Builder - bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true}) + benchmarkBuilding(b, name, buf) + } +} - if err := bld.StartQuestions(); err != nil { - b.Fatal("bld.StartQuestions():", err) - } - q := Question{ - Name: name, - Type: TypeA, - Class: ClassINET, - } - if err := bld.Question(q); err != nil { - b.Fatalf("bld.Question(%+v): %v", q, err) - } - - hdr := ResourceHeader{ - Name: name, - Class: ClassINET, - } - if err := bld.StartAnswers(); err != nil { - b.Fatal("bld.StartQuestions():", err) - } - - ar := AResource{[4]byte{}} - if err := bld.AResource(hdr, ar); err != nil { - b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err) - } - - aaar := AAAAResource{[16]byte{}} - if err := bld.AAAAResource(hdr, aaar); err != nil { - b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err) - } - - cnr := CNAMEResource{name} - if err := bld.CNAMEResource(hdr, cnr); err != nil { - b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err) - } - - nsr := NSResource{name} - if err := bld.NSResource(hdr, nsr); err != nil { - b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err) - } - - if _, err := bld.Finish(); err != nil { - b.Fatal("bld.Finish():", err) - } +func TestBuildingAllocs(t *testing.T) { + name, buf := benchmarkBuildingSetup() + if allocs := testing.AllocsPerRun(100, func() { benchmarkBuilding(t, name, buf) }); allocs > 0.5 { + t.Errorf("allocations during building: got = %f, want ~0", allocs) } } func smallTestMsg() Message { - name := mustNewName("example.com.") + name := MustNewName("example.com.") return Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -859,7 +1289,7 @@ func BenchmarkPack(b *testing.B) { for i := 0; i < b.N; i++ { if _, err := msg.Pack(); err != nil { - b.Fatal(err) + b.Fatal("Message.Pack() =", err) } } } @@ -872,13 +1302,13 @@ func BenchmarkAppendPack(b *testing.B) { for i := 0; i < b.N; i++ { if _, err := msg.AppendPack(buf[:0]); err != nil { - b.Fatal(err) + b.Fatal("Message.AppendPack() = ", err) } } } func largeTestMsg() Message { - name := mustNewName("foo.bar.example.com.") + name := MustNewName("foo.bar.example.com.") return Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -919,7 +1349,7 @@ func largeTestMsg() Message { Type: TypeCNAME, Class: ClassINET, }, - &CNAMEResource{mustNewName("alias.example.com.")}, + &CNAMEResource{MustNewName("alias.example.com.")}, }, { ResourceHeader{ @@ -928,8 +1358,8 @@ func largeTestMsg() Message { Class: ClassINET, }, &SOAResource{ - NS: mustNewName("ns1.example.com."), - MBox: mustNewName("mb.example.com."), + NS: MustNewName("ns1.example.com."), + MBox: MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, @@ -943,7 +1373,7 @@ func largeTestMsg() Message { Type: TypePTR, Class: ClassINET, }, - &PTRResource{mustNewName("ptr.example.com.")}, + &PTRResource{MustNewName("ptr.example.com.")}, }, { ResourceHeader{ @@ -953,7 +1383,7 @@ func largeTestMsg() Message { }, &MXResource{ 7, - mustNewName("mx.example.com."), + MustNewName("mx.example.com."), }, }, { @@ -966,7 +1396,7 @@ func largeTestMsg() Message { 8, 9, 11, - mustNewName("srv.example.com."), + MustNewName("srv.example.com."), }, }, }, @@ -977,7 +1407,7 @@ func largeTestMsg() Message { Type: TypeNS, Class: ClassINET, }, - &NSResource{mustNewName("ns1.example.com.")}, + &NSResource{MustNewName("ns1.example.com.")}, }, { ResourceHeader{ @@ -985,7 +1415,7 @@ func largeTestMsg() Message { Type: TypeNS, Class: ClassINET, }, - &NSResource{mustNewName("ns2.example.com.")}, + &NSResource{MustNewName("ns2.example.com.")}, }, }, Additionals: []Resource{ @@ -995,7 +1425,7 @@ func largeTestMsg() Message { Type: TypeTXT, Class: ClassINET, }, - &TXTResource{"So Long, and Thanks for All the Fish"}, + &TXTResource{[]string{"So Long, and Thanks for All the Fish"}}, }, { ResourceHeader{ @@ -1003,139 +1433,19 @@ func largeTestMsg() Message { Type: TypeTXT, Class: ClassINET, }, - &TXTResource{"Hamster Huey and the Gooey Kablooie"}, + &TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}}, + }, + { + mustEDNS0ResourceHeader(4096, 0xfe0|RCodeSuccess, false), + &OPTResource{ + Options: []Option{ + { + Code: 10, // see RFC 7873 + Data: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + }, + }, + }, }, }, } } - -const loremIpsum = ` -Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro -nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos, -magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas -regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei -nam ipsum assentior. - -Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum -facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque -no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem -reformidans et. Qui ei eros porro reformidans, ius suas veritus -torquatos ex. Mea te facer alterum consequat. - -Soleat torquatos democritum sed et, no mea congue appareat, facer -aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet -phaedrum ad nam. Ea detracto verterem liberavisse has, delectus -suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis -honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum -mollis. - -Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad -vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque -vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum -dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut -pro, vel ne saepe senserit consetetur. - -Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no -enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum -sententiae deterruisset ut. At suas timeam euismod cum, offendit -appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam -accusata intellegebat, noluisse instructior sea id. Nec te nonumes -habemus appellantur, quis dignissim vituperata eu nam. - -At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet -iisque an mea. Per eu dicant ponderum accommodare. Pri alienum -placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea -eligendi disputationi. Ius no tation everti impedit, ei magna quidam -mediocritatem pri. - -Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam, -ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo -has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut -iudico albucius his. - -Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue -dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse, -an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At -vis dicant abhorreant, utinam forensibus nec ne, mei te docendi -consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae -usu, dicit graeco disputando id has. - -Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec -torquatos sadipscing ei, ancillae molestie per in. Malis principes duo -ea, usu liber postulant ei. - -Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta -feugiat duo. Congue option meliore ex qui, noster invenire appellantur -ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an -probo minimum, et nam illud falli tempor. - -Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens -tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat -tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri. - -Ad oratio blandit aliquando pro. Vis et dolorum rationibus -philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et, -ne qui nisl verear saperet, vel te quaestio forensibus. Per odio -option delenit an. Alii placerat has no, in pri nihil platonem -cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea -an. - -Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat -accusam mea et. Elitr labitur albucius et pri, an labore feugait mel. -Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no -error volumus scripserit. In pro paulo iudico, quo ei dolorem -verterem, affert fabellas dissentiet ea vix. - -Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi -salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at -nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit -utroque vis, ex equidem detraxit temporibus has. - -Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas -pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad -mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata -interesset. Mel sapientem prodesset abhorreant et, oblique suscipit -eam id. - -An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens -inciderint no sea. Ea persius maluisset vix, ne vim appellantur -instructior, consul quidam definiebas pri id. Cum integre feugiat -pericula in, ex sed persius similique, mel ne natum dicit percipitur. - -Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore -neglegentur, mei tincidunt percipitur ei. Pro ad simul integre -rationibus. Eu vel alii honestatis definitiones, mea no nonumy -reprehendunt. - -Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix -adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat -duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum -debitis nostrum no, ut vel aliquid vivendo. - -Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi. -Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo -dolore impedit id eam, et aeque feugait assentior has. Quando sensibus -nec ex. Possit sensibus pri ad, unum mutat periculis cu vix. - -Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit -sonet tempor. No per solet aeterno deseruisse. Petentium salutandi -definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi -vis, modus offendit omittantur te mel. - -Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam -melius conceptam est ne, quo in minimum apeirian delicata, ut ius -porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu -his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te -per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis -ad idque fabellas intellegebat. - -Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut, -mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne -alia corpora invenire, alia prima soleat te cum. Eleifend posidonium -nam at. - -Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril -discere. Nec civibus officiis dissentiunt ex, est te liber ludus -elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit -comprehensam, nam te inermis delectus, saepe inermis senserit. -` diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go index cc5dc5d..5d05278 100644 --- a/vendor/golang.org/x/net/html/atom/gen.go +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -306,7 +306,7 @@ func (t *table) push(i uint32, depth int) bool { // The lists of element names and attribute keys were taken from // https://html.spec.whatwg.org/multipage/indices.html#index -// as of the "HTML Living Standard - Last Updated 18 September 2017" version. +// as of the "HTML Living Standard - Last Updated 16 April 2018" version. // "command", "keygen" and "menuitem" have been removed from the spec, // but are kept here for backwards compatibility. @@ -665,6 +665,7 @@ var eventHandlers = []string{ // extra are ad-hoc values not covered by any of the lists above. var extra = []string{ + "acronym", "align", "annotation", "annotation-xml", @@ -700,6 +701,8 @@ var extra = []string{ "plaintext", "prompt", "public", + "rb", + "rtc", "spacer", "strike", "svg", diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go index f74018e..2a93886 100644 --- a/vendor/golang.org/x/net/html/atom/table.go +++ b/vendor/golang.org/x/net/html/atom/table.go @@ -10,366 +10,369 @@ const ( Accept Atom = 0x1a06 AcceptCharset Atom = 0x1a0e Accesskey Atom = 0x2c09 - Action Atom = 0x25a06 - Address Atom = 0x6ed07 - Align Atom = 0x6d405 - Allowfullscreen Atom = 0x1f00f - Allowpaymentrequest Atom = 0x6913 - Allowusermedia Atom = 0x850e - Alt Atom = 0xb003 - Annotation Atom = 0x1b90a - AnnotationXml Atom = 0x1b90e - Applet Atom = 0x30106 - Area Atom = 0x34a04 - Article Atom = 0x3f007 - As Atom = 0xb902 - Aside Atom = 0xc105 - Async Atom = 0xb905 - Audio Atom = 0xcf05 - Autocomplete Atom = 0x2600c - Autofocus Atom = 0xeb09 - Autoplay Atom = 0x10608 + Acronym Atom = 0xaa07 + Action Atom = 0x27206 + Address Atom = 0x6f307 + Align Atom = 0xb105 + Allowfullscreen Atom = 0x2080f + Allowpaymentrequest Atom = 0xc113 + Allowusermedia Atom = 0xdd0e + Alt Atom = 0xf303 + Annotation Atom = 0x1c90a + AnnotationXml Atom = 0x1c90e + Applet Atom = 0x31906 + Area Atom = 0x35604 + Article Atom = 0x3fc07 + As Atom = 0x3c02 + Aside Atom = 0x10705 + Async Atom = 0xff05 + Audio Atom = 0x11505 + Autocomplete Atom = 0x2780c + Autofocus Atom = 0x12109 + Autoplay Atom = 0x13c08 B Atom = 0x101 - Base Atom = 0x11504 - Basefont Atom = 0x11508 - Bdi Atom = 0x16103 - Bdo Atom = 0x13403 - Bgsound Atom = 0x14707 - Big Atom = 0x15903 - Blink Atom = 0x15c05 - Blockquote Atom = 0x1680a + Base Atom = 0x3b04 + Basefont Atom = 0x3b08 + Bdi Atom = 0xba03 + Bdo Atom = 0x14b03 + Bgsound Atom = 0x15e07 + Big Atom = 0x17003 + Blink Atom = 0x17305 + Blockquote Atom = 0x1870a Body Atom = 0x2804 Br Atom = 0x202 - Button Atom = 0x17206 - Canvas Atom = 0xbd06 - Caption Atom = 0x21907 - Center Atom = 0x20806 - Challenge Atom = 0x28309 + Button Atom = 0x19106 + Canvas Atom = 0x10306 + Caption Atom = 0x23107 + Center Atom = 0x22006 + Challenge Atom = 0x29b09 Charset Atom = 0x2107 - Checked Atom = 0x46d07 - Cite Atom = 0x55804 - Class Atom = 0x5b905 - Code Atom = 0x19004 - Col Atom = 0x19703 - Colgroup Atom = 0x19708 - Color Atom = 0x1af05 - Cols Atom = 0x1b404 - Colspan Atom = 0x1b407 - Command Atom = 0x1c707 - Content Atom = 0x57f07 - Contenteditable Atom = 0x57f0f - Contextmenu Atom = 0x3740b - Controls Atom = 0x1ce08 - Coords Atom = 0x1da06 - Crossorigin Atom = 0x1e30b - Data Atom = 0x49904 - Datalist Atom = 0x49908 - Datetime Atom = 0x2a008 - Dd Atom = 0x2bf02 - Default Atom = 0xc407 - Defer Atom = 0x19205 - Del Atom = 0x44603 - Desc Atom = 0x55504 - Details Atom = 0x4607 - Dfn Atom = 0x5f03 - Dialog Atom = 0x16206 - Dir Atom = 0xa303 - Dirname Atom = 0xa307 - Disabled Atom = 0x14d08 - Div Atom = 0x15403 - Dl Atom = 0x5e202 - Download Atom = 0x45708 - Draggable Atom = 0x18309 - Dropzone Atom = 0x3f908 - Dt Atom = 0x64702 - Em Atom = 0x4202 - Embed Atom = 0x4205 - Enctype Atom = 0x27507 - Face Atom = 0x20604 - Fieldset Atom = 0x20e08 - Figcaption Atom = 0x2160a - Figure Atom = 0x23006 - Font Atom = 0x11904 - Footer Atom = 0xb306 - For Atom = 0x23c03 - ForeignObject Atom = 0x23c0d - Foreignobject Atom = 0x2490d - Form Atom = 0x25604 - Formaction Atom = 0x2560a - Formenctype Atom = 0x2710b - Formmethod Atom = 0x28c0a - Formnovalidate Atom = 0x2960e - Formtarget Atom = 0x2a80a - Frame Atom = 0x5705 - Frameset Atom = 0x5708 - H1 Atom = 0x14502 - H2 Atom = 0x2c602 - H3 Atom = 0x2f502 - H4 Atom = 0x33902 - H5 Atom = 0x34302 - H6 Atom = 0x64902 - Head Atom = 0x32504 - Header Atom = 0x32506 - Headers Atom = 0x32507 - Height Atom = 0x12c06 - Hgroup Atom = 0x2b206 - Hidden Atom = 0x2bd06 - High Atom = 0x2c304 - Hr Atom = 0x14002 - Href Atom = 0x2c804 - Hreflang Atom = 0x2c808 - Html Atom = 0x13004 - HttpEquiv Atom = 0x2d00a + Checked Atom = 0x47907 + Cite Atom = 0x19c04 + Class Atom = 0x56405 + Code Atom = 0x5c504 + Col Atom = 0x1ab03 + Colgroup Atom = 0x1ab08 + Color Atom = 0x1bf05 + Cols Atom = 0x1c404 + Colspan Atom = 0x1c407 + Command Atom = 0x1d707 + Content Atom = 0x58b07 + Contenteditable Atom = 0x58b0f + Contextmenu Atom = 0x3800b + Controls Atom = 0x1de08 + Coords Atom = 0x1ea06 + Crossorigin Atom = 0x1fb0b + Data Atom = 0x4a504 + Datalist Atom = 0x4a508 + Datetime Atom = 0x2b808 + Dd Atom = 0x2d702 + Default Atom = 0x10a07 + Defer Atom = 0x5c705 + Del Atom = 0x45203 + Desc Atom = 0x56104 + Details Atom = 0x7207 + Dfn Atom = 0x8703 + Dialog Atom = 0xbb06 + Dir Atom = 0x9303 + Dirname Atom = 0x9307 + Disabled Atom = 0x16408 + Div Atom = 0x16b03 + Dl Atom = 0x5e602 + Download Atom = 0x46308 + Draggable Atom = 0x17a09 + Dropzone Atom = 0x40508 + Dt Atom = 0x64b02 + Em Atom = 0x6e02 + Embed Atom = 0x6e05 + Enctype Atom = 0x28d07 + Face Atom = 0x21e04 + Fieldset Atom = 0x22608 + Figcaption Atom = 0x22e0a + Figure Atom = 0x24806 + Font Atom = 0x3f04 + Footer Atom = 0xf606 + For Atom = 0x25403 + ForeignObject Atom = 0x2540d + Foreignobject Atom = 0x2610d + Form Atom = 0x26e04 + Formaction Atom = 0x26e0a + Formenctype Atom = 0x2890b + Formmethod Atom = 0x2a40a + Formnovalidate Atom = 0x2ae0e + Formtarget Atom = 0x2c00a + Frame Atom = 0x8b05 + Frameset Atom = 0x8b08 + H1 Atom = 0x15c02 + H2 Atom = 0x2de02 + H3 Atom = 0x30d02 + H4 Atom = 0x34502 + H5 Atom = 0x34f02 + H6 Atom = 0x64d02 + Head Atom = 0x33104 + Header Atom = 0x33106 + Headers Atom = 0x33107 + Height Atom = 0x5206 + Hgroup Atom = 0x2ca06 + Hidden Atom = 0x2d506 + High Atom = 0x2db04 + Hr Atom = 0x15702 + Href Atom = 0x2e004 + Hreflang Atom = 0x2e008 + Html Atom = 0x5604 + HttpEquiv Atom = 0x2e80a I Atom = 0x601 - Icon Atom = 0x57e04 - Id Atom = 0xc302 - Iframe Atom = 0x2e406 - Image Atom = 0x2ea05 - Img Atom = 0x2ef03 - Input Atom = 0x43f05 - Inputmode Atom = 0x43f09 - Ins Atom = 0x1ec03 - Integrity Atom = 0x22709 - Is Atom = 0x14e02 - Isindex Atom = 0x2f707 - Ismap Atom = 0x2fe05 - Itemid Atom = 0x37f06 - Itemprop Atom = 0x55908 - Itemref Atom = 0x3c107 - Itemscope Atom = 0x66d09 - Itemtype Atom = 0x30708 - Kbd Atom = 0x16003 + Icon Atom = 0x58a04 + Id Atom = 0x10902 + Iframe Atom = 0x2fc06 + Image Atom = 0x30205 + Img Atom = 0x30703 + Input Atom = 0x44b05 + Inputmode Atom = 0x44b09 + Ins Atom = 0x20403 + Integrity Atom = 0x23f09 + Is Atom = 0x16502 + Isindex Atom = 0x30f07 + Ismap Atom = 0x31605 + Itemid Atom = 0x38b06 + Itemprop Atom = 0x19d08 + Itemref Atom = 0x3cd07 + Itemscope Atom = 0x67109 + Itemtype Atom = 0x31f08 + Kbd Atom = 0xb903 Keygen Atom = 0x3206 - Keytype Atom = 0x7e07 - Kind Atom = 0x18004 - Label Atom = 0xda05 - Lang Atom = 0x2cc04 - Legend Atom = 0x18a06 - Li Atom = 0x11102 - Link Atom = 0x15d04 - List Atom = 0x49d04 - Listing Atom = 0x49d07 - Loop Atom = 0xde04 - Low Atom = 0x6b03 + Keytype Atom = 0xd607 + Kind Atom = 0x17704 + Label Atom = 0x5905 + Lang Atom = 0x2e404 + Legend Atom = 0x18106 + Li Atom = 0xb202 + Link Atom = 0x17404 + List Atom = 0x4a904 + Listing Atom = 0x4a907 + Loop Atom = 0x5d04 + Low Atom = 0xc303 Main Atom = 0x1004 - Malignmark Atom = 0x6d30a - Manifest Atom = 0x30f08 - Map Atom = 0x30003 - Mark Atom = 0x6d904 - Marquee Atom = 0x31b07 - Math Atom = 0x32204 - Max Atom = 0x33103 - Maxlength Atom = 0x33109 - Media Atom = 0x8e05 - Mediagroup Atom = 0x8e0a - Menu Atom = 0x37b04 - Menuitem Atom = 0x37b08 - Meta Atom = 0x4ac04 - Meter Atom = 0xa805 - Method Atom = 0x29006 - Mglyph Atom = 0x2f006 - Mi Atom = 0x33b02 - Min Atom = 0x33b03 - Minlength Atom = 0x33b09 - Mn Atom = 0x29902 - Mo Atom = 0x6302 - Ms Atom = 0x67002 - Mtext Atom = 0x34505 - Multiple Atom = 0x35308 - Muted Atom = 0x35b05 - Name Atom = 0xa604 + Malignmark Atom = 0xb00a + Manifest Atom = 0x6d708 + Map Atom = 0x31803 + Mark Atom = 0xb604 + Marquee Atom = 0x32707 + Math Atom = 0x32e04 + Max Atom = 0x33d03 + Maxlength Atom = 0x33d09 + Media Atom = 0xe605 + Mediagroup Atom = 0xe60a + Menu Atom = 0x38704 + Menuitem Atom = 0x38708 + Meta Atom = 0x4b804 + Meter Atom = 0x9805 + Method Atom = 0x2a806 + Mglyph Atom = 0x30806 + Mi Atom = 0x34702 + Min Atom = 0x34703 + Minlength Atom = 0x34709 + Mn Atom = 0x2b102 + Mo Atom = 0xa402 + Ms Atom = 0x67402 + Mtext Atom = 0x35105 + Multiple Atom = 0x35f08 + Muted Atom = 0x36705 + Name Atom = 0x9604 Nav Atom = 0x1303 Nobr Atom = 0x3704 - Noembed Atom = 0x4007 - Noframes Atom = 0x5508 - Nomodule Atom = 0x6108 - Nonce Atom = 0x56205 - Noscript Atom = 0x1fe08 - Novalidate Atom = 0x29a0a - Object Atom = 0x25006 - Ol Atom = 0x10102 - Onabort Atom = 0x17607 - Onafterprint Atom = 0x21e0c - Onautocomplete Atom = 0x25e0e - Onautocompleteerror Atom = 0x25e13 - Onauxclick Atom = 0x61b0a - Onbeforeprint Atom = 0x69a0d - Onbeforeunload Atom = 0x6e10e - Onblur Atom = 0x5c206 - Oncancel Atom = 0xd308 - Oncanplay Atom = 0x13609 - Oncanplaythrough Atom = 0x13610 - Onchange Atom = 0x40f08 - Onclick Atom = 0x2dd07 - Onclose Atom = 0x36007 - Oncontextmenu Atom = 0x3720d - Oncopy Atom = 0x38506 - Oncuechange Atom = 0x38b0b - Oncut Atom = 0x39605 - Ondblclick Atom = 0x39b0a - Ondrag Atom = 0x3a506 - Ondragend Atom = 0x3a509 - Ondragenter Atom = 0x3ae0b - Ondragexit Atom = 0x3b90a - Ondragleave Atom = 0x3d30b - Ondragover Atom = 0x3de0a - Ondragstart Atom = 0x3e80b - Ondrop Atom = 0x3f706 - Ondurationchange Atom = 0x40710 - Onemptied Atom = 0x3fe09 - Onended Atom = 0x41707 - Onerror Atom = 0x41e07 - Onfocus Atom = 0x42507 - Onhashchange Atom = 0x4310c - Oninput Atom = 0x43d07 - Oninvalid Atom = 0x44909 - Onkeydown Atom = 0x45209 - Onkeypress Atom = 0x45f0a - Onkeyup Atom = 0x47407 - Onlanguagechange Atom = 0x48110 - Onload Atom = 0x49106 - Onloadeddata Atom = 0x4910c - Onloadedmetadata Atom = 0x4a410 - Onloadend Atom = 0x4ba09 - Onloadstart Atom = 0x4c30b - Onmessage Atom = 0x4ce09 - Onmessageerror Atom = 0x4ce0e - Onmousedown Atom = 0x4dc0b - Onmouseenter Atom = 0x4e70c - Onmouseleave Atom = 0x4f30c - Onmousemove Atom = 0x4ff0b - Onmouseout Atom = 0x50a0a - Onmouseover Atom = 0x5170b - Onmouseup Atom = 0x52209 - Onmousewheel Atom = 0x5300c - Onoffline Atom = 0x53c09 - Ononline Atom = 0x54508 - Onpagehide Atom = 0x54d0a - Onpageshow Atom = 0x5670a - Onpaste Atom = 0x57307 - Onpause Atom = 0x58e07 - Onplay Atom = 0x59806 - Onplaying Atom = 0x59809 - Onpopstate Atom = 0x5a10a - Onprogress Atom = 0x5ab0a - Onratechange Atom = 0x5c80c - Onrejectionhandled Atom = 0x5d412 - Onreset Atom = 0x5e607 - Onresize Atom = 0x5ed08 - Onscroll Atom = 0x5fc08 - Onsecuritypolicyviolation Atom = 0x60419 - Onseeked Atom = 0x62508 - Onseeking Atom = 0x62d09 - Onselect Atom = 0x63608 - Onshow Atom = 0x64006 - Onsort Atom = 0x64b06 - Onstalled Atom = 0x65509 - Onstorage Atom = 0x65e09 - Onsubmit Atom = 0x66708 - Onsuspend Atom = 0x67709 - Ontimeupdate Atom = 0x11a0c - Ontoggle Atom = 0x68008 - Onunhandledrejection Atom = 0x68814 - Onunload Atom = 0x6a708 - Onvolumechange Atom = 0x6af0e - Onwaiting Atom = 0x6bd09 - Onwheel Atom = 0x6c607 - Open Atom = 0x55f04 - Optgroup Atom = 0xe008 - Optimum Atom = 0x6cd07 - Option Atom = 0x6dd06 - Output Atom = 0x51106 + Noembed Atom = 0x6c07 + Noframes Atom = 0x8908 + Nomodule Atom = 0xa208 + Nonce Atom = 0x1a605 + Noscript Atom = 0x21608 + Novalidate Atom = 0x2b20a + Object Atom = 0x26806 + Ol Atom = 0x13702 + Onabort Atom = 0x19507 + Onafterprint Atom = 0x2360c + Onautocomplete Atom = 0x2760e + Onautocompleteerror Atom = 0x27613 + Onauxclick Atom = 0x61f0a + Onbeforeprint Atom = 0x69e0d + Onbeforeunload Atom = 0x6e70e + Onblur Atom = 0x56d06 + Oncancel Atom = 0x11908 + Oncanplay Atom = 0x14d09 + Oncanplaythrough Atom = 0x14d10 + Onchange Atom = 0x41b08 + Onclick Atom = 0x2f507 + Onclose Atom = 0x36c07 + Oncontextmenu Atom = 0x37e0d + Oncopy Atom = 0x39106 + Oncuechange Atom = 0x3970b + Oncut Atom = 0x3a205 + Ondblclick Atom = 0x3a70a + Ondrag Atom = 0x3b106 + Ondragend Atom = 0x3b109 + Ondragenter Atom = 0x3ba0b + Ondragexit Atom = 0x3c50a + Ondragleave Atom = 0x3df0b + Ondragover Atom = 0x3ea0a + Ondragstart Atom = 0x3f40b + Ondrop Atom = 0x40306 + Ondurationchange Atom = 0x41310 + Onemptied Atom = 0x40a09 + Onended Atom = 0x42307 + Onerror Atom = 0x42a07 + Onfocus Atom = 0x43107 + Onhashchange Atom = 0x43d0c + Oninput Atom = 0x44907 + Oninvalid Atom = 0x45509 + Onkeydown Atom = 0x45e09 + Onkeypress Atom = 0x46b0a + Onkeyup Atom = 0x48007 + Onlanguagechange Atom = 0x48d10 + Onload Atom = 0x49d06 + Onloadeddata Atom = 0x49d0c + Onloadedmetadata Atom = 0x4b010 + Onloadend Atom = 0x4c609 + Onloadstart Atom = 0x4cf0b + Onmessage Atom = 0x4da09 + Onmessageerror Atom = 0x4da0e + Onmousedown Atom = 0x4e80b + Onmouseenter Atom = 0x4f30c + Onmouseleave Atom = 0x4ff0c + Onmousemove Atom = 0x50b0b + Onmouseout Atom = 0x5160a + Onmouseover Atom = 0x5230b + Onmouseup Atom = 0x52e09 + Onmousewheel Atom = 0x53c0c + Onoffline Atom = 0x54809 + Ononline Atom = 0x55108 + Onpagehide Atom = 0x5590a + Onpageshow Atom = 0x5730a + Onpaste Atom = 0x57f07 + Onpause Atom = 0x59a07 + Onplay Atom = 0x5a406 + Onplaying Atom = 0x5a409 + Onpopstate Atom = 0x5ad0a + Onprogress Atom = 0x5b70a + Onratechange Atom = 0x5cc0c + Onrejectionhandled Atom = 0x5d812 + Onreset Atom = 0x5ea07 + Onresize Atom = 0x5f108 + Onscroll Atom = 0x60008 + Onsecuritypolicyviolation Atom = 0x60819 + Onseeked Atom = 0x62908 + Onseeking Atom = 0x63109 + Onselect Atom = 0x63a08 + Onshow Atom = 0x64406 + Onsort Atom = 0x64f06 + Onstalled Atom = 0x65909 + Onstorage Atom = 0x66209 + Onsubmit Atom = 0x66b08 + Onsuspend Atom = 0x67b09 + Ontimeupdate Atom = 0x400c + Ontoggle Atom = 0x68408 + Onunhandledrejection Atom = 0x68c14 + Onunload Atom = 0x6ab08 + Onvolumechange Atom = 0x6b30e + Onwaiting Atom = 0x6c109 + Onwheel Atom = 0x6ca07 + Open Atom = 0x1a304 + Optgroup Atom = 0x5f08 + Optimum Atom = 0x6d107 + Option Atom = 0x6e306 + Output Atom = 0x51d06 P Atom = 0xc01 Param Atom = 0xc05 - Pattern Atom = 0x4f07 - Picture Atom = 0x9707 - Ping Atom = 0xe704 - Placeholder Atom = 0xfb0b - Plaintext Atom = 0x19e09 - Playsinline Atom = 0x10a0b - Poster Atom = 0x2b706 - Pre Atom = 0x46403 - Preload Atom = 0x47a07 - Progress Atom = 0x5ad08 - Prompt Atom = 0x52a06 - Public Atom = 0x57a06 - Q Atom = 0x7701 + Pattern Atom = 0x6607 + Picture Atom = 0x7b07 + Ping Atom = 0xef04 + Placeholder Atom = 0x1310b + Plaintext Atom = 0x1b209 + Playsinline Atom = 0x1400b + Poster Atom = 0x2cf06 + Pre Atom = 0x47003 + Preload Atom = 0x48607 + Progress Atom = 0x5b908 + Prompt Atom = 0x53606 + Public Atom = 0x58606 + Q Atom = 0xcf01 Radiogroup Atom = 0x30a - Readonly Atom = 0x34b08 - Referrerpolicy Atom = 0x3c50e - Rel Atom = 0x47b03 - Required Atom = 0x23408 - Reversed Atom = 0x9c08 - Rows Atom = 0x3a04 - Rowspan Atom = 0x3a07 - Rp Atom = 0x22402 - Rt Atom = 0x17b02 - Ruby Atom = 0xac04 + Rb Atom = 0x3a02 + Readonly Atom = 0x35708 + Referrerpolicy Atom = 0x3d10e + Rel Atom = 0x48703 + Required Atom = 0x24c08 + Reversed Atom = 0x8008 + Rows Atom = 0x9c04 + Rowspan Atom = 0x9c07 + Rp Atom = 0x23c02 + Rt Atom = 0x19a02 + Rtc Atom = 0x19a03 + Ruby Atom = 0xfb04 S Atom = 0x2501 - Samp Atom = 0x4c04 - Sandbox Atom = 0xf307 - Scope Atom = 0x67105 - Scoped Atom = 0x67106 - Script Atom = 0x20006 - Seamless Atom = 0x36508 - Section Atom = 0x5bd07 - Select Atom = 0x63806 - Selected Atom = 0x63808 - Shape Atom = 0x1d505 - Size Atom = 0x5f104 - Sizes Atom = 0x5f105 - Slot Atom = 0x1df04 - Small Atom = 0x1ee05 - Sortable Atom = 0x64d08 - Sorted Atom = 0x32b06 - Source Atom = 0x36c06 - Spacer Atom = 0x42b06 - Span Atom = 0x3d04 - Spellcheck Atom = 0x4680a - Src Atom = 0x5b403 - Srcdoc Atom = 0x5b406 - Srclang Atom = 0x5f507 - Srcset Atom = 0x6f306 - Start Atom = 0x3ee05 - Step Atom = 0x57704 - Strike Atom = 0x7a06 - Strong Atom = 0x31506 - Style Atom = 0x6f905 - Sub Atom = 0x66903 - Summary Atom = 0x6fe07 - Sup Atom = 0x70503 - Svg Atom = 0x70803 - System Atom = 0x70b06 - Tabindex Atom = 0x4b208 - Table Atom = 0x58905 - Target Atom = 0x2ac06 + Samp Atom = 0x7804 + Sandbox Atom = 0x12907 + Scope Atom = 0x67505 + Scoped Atom = 0x67506 + Script Atom = 0x21806 + Seamless Atom = 0x37108 + Section Atom = 0x56807 + Select Atom = 0x63c06 + Selected Atom = 0x63c08 + Shape Atom = 0x1e505 + Size Atom = 0x5f504 + Sizes Atom = 0x5f505 + Slot Atom = 0x1ef04 + Small Atom = 0x20605 + Sortable Atom = 0x65108 + Sorted Atom = 0x33706 + Source Atom = 0x37806 + Spacer Atom = 0x43706 + Span Atom = 0x9f04 + Spellcheck Atom = 0x4740a + Src Atom = 0x5c003 + Srcdoc Atom = 0x5c006 + Srclang Atom = 0x5f907 + Srcset Atom = 0x6f906 + Start Atom = 0x3fa05 + Step Atom = 0x58304 + Strike Atom = 0xd206 + Strong Atom = 0x6dd06 + Style Atom = 0x6ff05 + Sub Atom = 0x66d03 + Summary Atom = 0x70407 + Sup Atom = 0x70b03 + Svg Atom = 0x70e03 + System Atom = 0x71106 + Tabindex Atom = 0x4be08 + Table Atom = 0x59505 + Target Atom = 0x2c406 Tbody Atom = 0x2705 - Td Atom = 0x5e02 - Template Atom = 0x70e08 - Textarea Atom = 0x34608 - Tfoot Atom = 0xb205 - Th Atom = 0x13f02 - Thead Atom = 0x32405 - Time Atom = 0x11c04 - Title Atom = 0xca05 - Tr Atom = 0x7402 - Track Atom = 0x17c05 - Translate Atom = 0x1a609 - Tt Atom = 0x5102 - Type Atom = 0x8104 - Typemustmatch Atom = 0x2780d + Td Atom = 0x9202 + Template Atom = 0x71408 + Textarea Atom = 0x35208 + Tfoot Atom = 0xf505 + Th Atom = 0x15602 + Thead Atom = 0x33005 + Time Atom = 0x4204 + Title Atom = 0x11005 + Tr Atom = 0xcc02 + Track Atom = 0x1ba05 + Translate Atom = 0x1f209 + Tt Atom = 0x6802 + Type Atom = 0xd904 + Typemustmatch Atom = 0x2900d U Atom = 0xb01 - Ul Atom = 0x6602 - Updateviacache Atom = 0x1200e - Usemap Atom = 0x59206 + Ul Atom = 0xa702 + Updateviacache Atom = 0x460e + Usemap Atom = 0x59e06 Value Atom = 0x1505 - Var Atom = 0x15603 - Video Atom = 0x2d905 - Wbr Atom = 0x57003 - Width Atom = 0x64505 - Workertype Atom = 0x7160a - Wrap Atom = 0x72004 - Xmp Atom = 0xf903 + Var Atom = 0x16d03 + Video Atom = 0x2f105 + Wbr Atom = 0x57c03 + Width Atom = 0x64905 + Workertype Atom = 0x71c0a + Wrap Atom = 0x72604 + Xmp Atom = 0x12f03 ) const hash0 = 0x81cdf10e @@ -377,401 +380,404 @@ const hash0 = 0x81cdf10e const maxAtomLen = 25 var table = [1 << 9]Atom{ - 0x1: 0x8e0a, // mediagroup - 0x2: 0x2cc04, // lang + 0x1: 0xe60a, // mediagroup + 0x2: 0x2e404, // lang 0x4: 0x2c09, // accesskey - 0x5: 0x5708, // frameset - 0x7: 0x63608, // onselect - 0x8: 0x70b06, // system - 0xa: 0x64505, // width - 0xc: 0x2710b, // formenctype - 0xd: 0x10102, // ol - 0xe: 0x38b0b, // oncuechange - 0x10: 0x13403, // bdo - 0x11: 0xcf05, // audio - 0x12: 0x18309, // draggable - 0x14: 0x2d905, // video - 0x15: 0x29902, // mn - 0x16: 0x37b04, // menu - 0x17: 0x2b706, // poster - 0x19: 0xb306, // footer - 0x1a: 0x29006, // method - 0x1b: 0x2a008, // datetime - 0x1c: 0x17607, // onabort - 0x1d: 0x1200e, // updateviacache - 0x1e: 0xb905, // async - 0x1f: 0x49106, // onload - 0x21: 0xd308, // oncancel - 0x22: 0x62508, // onseeked - 0x23: 0x2ea05, // image - 0x24: 0x5d412, // onrejectionhandled - 0x26: 0x15d04, // link - 0x27: 0x51106, // output - 0x28: 0x32504, // head - 0x29: 0x4f30c, // onmouseleave - 0x2a: 0x57307, // onpaste - 0x2b: 0x59809, // onplaying - 0x2c: 0x1b407, // colspan - 0x2f: 0x1af05, // color - 0x30: 0x5f104, // size - 0x31: 0x2d00a, // http-equiv + 0x5: 0x8b08, // frameset + 0x7: 0x63a08, // onselect + 0x8: 0x71106, // system + 0xa: 0x64905, // width + 0xc: 0x2890b, // formenctype + 0xd: 0x13702, // ol + 0xe: 0x3970b, // oncuechange + 0x10: 0x14b03, // bdo + 0x11: 0x11505, // audio + 0x12: 0x17a09, // draggable + 0x14: 0x2f105, // video + 0x15: 0x2b102, // mn + 0x16: 0x38704, // menu + 0x17: 0x2cf06, // poster + 0x19: 0xf606, // footer + 0x1a: 0x2a806, // method + 0x1b: 0x2b808, // datetime + 0x1c: 0x19507, // onabort + 0x1d: 0x460e, // updateviacache + 0x1e: 0xff05, // async + 0x1f: 0x49d06, // onload + 0x21: 0x11908, // oncancel + 0x22: 0x62908, // onseeked + 0x23: 0x30205, // image + 0x24: 0x5d812, // onrejectionhandled + 0x26: 0x17404, // link + 0x27: 0x51d06, // output + 0x28: 0x33104, // head + 0x29: 0x4ff0c, // onmouseleave + 0x2a: 0x57f07, // onpaste + 0x2b: 0x5a409, // onplaying + 0x2c: 0x1c407, // colspan + 0x2f: 0x1bf05, // color + 0x30: 0x5f504, // size + 0x31: 0x2e80a, // http-equiv 0x33: 0x601, // i - 0x34: 0x54d0a, // onpagehide - 0x35: 0x68814, // onunhandledrejection - 0x37: 0x41e07, // onerror - 0x3a: 0x11508, // basefont + 0x34: 0x5590a, // onpagehide + 0x35: 0x68c14, // onunhandledrejection + 0x37: 0x42a07, // onerror + 0x3a: 0x3b08, // basefont 0x3f: 0x1303, // nav - 0x40: 0x18004, // kind - 0x41: 0x34b08, // readonly - 0x42: 0x2f006, // mglyph - 0x44: 0x11102, // li - 0x46: 0x2bd06, // hidden - 0x47: 0x70803, // svg - 0x48: 0x57704, // step - 0x49: 0x22709, // integrity - 0x4a: 0x57a06, // public - 0x4c: 0x19703, // col - 0x4d: 0x1680a, // blockquote - 0x4e: 0x34302, // h5 - 0x50: 0x5ad08, // progress - 0x51: 0x5f105, // sizes - 0x52: 0x33902, // h4 - 0x56: 0x32405, // thead - 0x57: 0x7e07, // keytype - 0x58: 0x5ab0a, // onprogress - 0x59: 0x43f09, // inputmode - 0x5a: 0x3a509, // ondragend - 0x5d: 0x39605, // oncut - 0x5e: 0x42b06, // spacer - 0x5f: 0x19708, // colgroup - 0x62: 0x14e02, // is - 0x65: 0xb902, // as - 0x66: 0x53c09, // onoffline - 0x67: 0x32b06, // sorted - 0x69: 0x48110, // onlanguagechange - 0x6c: 0x4310c, // onhashchange - 0x6d: 0xa604, // name - 0x6e: 0xb205, // tfoot - 0x6f: 0x55504, // desc - 0x70: 0x33103, // max - 0x72: 0x1da06, // coords - 0x73: 0x2f502, // h3 - 0x74: 0x6e10e, // onbeforeunload - 0x75: 0x3a04, // rows - 0x76: 0x63806, // select - 0x77: 0xa805, // meter - 0x78: 0x37f06, // itemid - 0x79: 0x5300c, // onmousewheel - 0x7a: 0x5b406, // srcdoc - 0x7d: 0x17c05, // track - 0x7f: 0x30708, // itemtype - 0x82: 0x6302, // mo - 0x83: 0x40f08, // onchange - 0x84: 0x32507, // headers - 0x85: 0x5c80c, // onratechange - 0x86: 0x60419, // onsecuritypolicyviolation - 0x88: 0x49908, // datalist - 0x89: 0x4dc0b, // onmousedown - 0x8a: 0x1df04, // slot - 0x8b: 0x4a410, // onloadedmetadata + 0x40: 0x17704, // kind + 0x41: 0x35708, // readonly + 0x42: 0x30806, // mglyph + 0x44: 0xb202, // li + 0x46: 0x2d506, // hidden + 0x47: 0x70e03, // svg + 0x48: 0x58304, // step + 0x49: 0x23f09, // integrity + 0x4a: 0x58606, // public + 0x4c: 0x1ab03, // col + 0x4d: 0x1870a, // blockquote + 0x4e: 0x34f02, // h5 + 0x50: 0x5b908, // progress + 0x51: 0x5f505, // sizes + 0x52: 0x34502, // h4 + 0x56: 0x33005, // thead + 0x57: 0xd607, // keytype + 0x58: 0x5b70a, // onprogress + 0x59: 0x44b09, // inputmode + 0x5a: 0x3b109, // ondragend + 0x5d: 0x3a205, // oncut + 0x5e: 0x43706, // spacer + 0x5f: 0x1ab08, // colgroup + 0x62: 0x16502, // is + 0x65: 0x3c02, // as + 0x66: 0x54809, // onoffline + 0x67: 0x33706, // sorted + 0x69: 0x48d10, // onlanguagechange + 0x6c: 0x43d0c, // onhashchange + 0x6d: 0x9604, // name + 0x6e: 0xf505, // tfoot + 0x6f: 0x56104, // desc + 0x70: 0x33d03, // max + 0x72: 0x1ea06, // coords + 0x73: 0x30d02, // h3 + 0x74: 0x6e70e, // onbeforeunload + 0x75: 0x9c04, // rows + 0x76: 0x63c06, // select + 0x77: 0x9805, // meter + 0x78: 0x38b06, // itemid + 0x79: 0x53c0c, // onmousewheel + 0x7a: 0x5c006, // srcdoc + 0x7d: 0x1ba05, // track + 0x7f: 0x31f08, // itemtype + 0x82: 0xa402, // mo + 0x83: 0x41b08, // onchange + 0x84: 0x33107, // headers + 0x85: 0x5cc0c, // onratechange + 0x86: 0x60819, // onsecuritypolicyviolation + 0x88: 0x4a508, // datalist + 0x89: 0x4e80b, // onmousedown + 0x8a: 0x1ef04, // slot + 0x8b: 0x4b010, // onloadedmetadata 0x8c: 0x1a06, // accept - 0x8d: 0x25006, // object - 0x91: 0x6af0e, // onvolumechange + 0x8d: 0x26806, // object + 0x91: 0x6b30e, // onvolumechange 0x92: 0x2107, // charset - 0x93: 0x25e13, // onautocompleteerror - 0x94: 0x6913, // allowpaymentrequest + 0x93: 0x27613, // onautocompleteerror + 0x94: 0xc113, // allowpaymentrequest 0x95: 0x2804, // body - 0x96: 0xc407, // default - 0x97: 0x63808, // selected - 0x98: 0x20604, // face - 0x99: 0x1d505, // shape - 0x9b: 0x68008, // ontoggle - 0x9e: 0x64702, // dt - 0x9f: 0x6d904, // mark + 0x96: 0x10a07, // default + 0x97: 0x63c08, // selected + 0x98: 0x21e04, // face + 0x99: 0x1e505, // shape + 0x9b: 0x68408, // ontoggle + 0x9e: 0x64b02, // dt + 0x9f: 0xb604, // mark 0xa1: 0xb01, // u - 0xa4: 0x6a708, // onunload - 0xa5: 0xde04, // loop - 0xa6: 0x14d08, // disabled - 0xaa: 0x41707, // onended - 0xab: 0x6d30a, // malignmark - 0xad: 0x67709, // onsuspend - 0xae: 0x34505, // mtext - 0xaf: 0x64b06, // onsort - 0xb0: 0x55908, // itemprop - 0xb3: 0x66d09, // itemscope - 0xb4: 0x15c05, // blink - 0xb6: 0x3a506, // ondrag - 0xb7: 0x6602, // ul - 0xb8: 0x25604, // form - 0xb9: 0xf307, // sandbox - 0xba: 0x5705, // frame + 0xa4: 0x6ab08, // onunload + 0xa5: 0x5d04, // loop + 0xa6: 0x16408, // disabled + 0xaa: 0x42307, // onended + 0xab: 0xb00a, // malignmark + 0xad: 0x67b09, // onsuspend + 0xae: 0x35105, // mtext + 0xaf: 0x64f06, // onsort + 0xb0: 0x19d08, // itemprop + 0xb3: 0x67109, // itemscope + 0xb4: 0x17305, // blink + 0xb6: 0x3b106, // ondrag + 0xb7: 0xa702, // ul + 0xb8: 0x26e04, // form + 0xb9: 0x12907, // sandbox + 0xba: 0x8b05, // frame 0xbb: 0x1505, // value - 0xbc: 0x65e09, // onstorage - 0xc0: 0x17b02, // rt + 0xbc: 0x66209, // onstorage + 0xbf: 0xaa07, // acronym + 0xc0: 0x19a02, // rt 0xc2: 0x202, // br - 0xc3: 0x20e08, // fieldset - 0xc4: 0x2780d, // typemustmatch - 0xc5: 0x6108, // nomodule - 0xc6: 0x4007, // noembed - 0xc7: 0x69a0d, // onbeforeprint - 0xc8: 0x17206, // button - 0xc9: 0x2dd07, // onclick - 0xca: 0x6fe07, // summary - 0xcd: 0xac04, // ruby - 0xce: 0x5b905, // class - 0xcf: 0x3e80b, // ondragstart - 0xd0: 0x21907, // caption - 0xd4: 0x850e, // allowusermedia - 0xd5: 0x4c30b, // onloadstart - 0xd9: 0x15403, // div - 0xda: 0x49d04, // list - 0xdb: 0x32204, // math - 0xdc: 0x43f05, // input - 0xdf: 0x3de0a, // ondragover - 0xe0: 0x2c602, // h2 - 0xe2: 0x19e09, // plaintext - 0xe4: 0x4e70c, // onmouseenter - 0xe7: 0x46d07, // checked - 0xe8: 0x46403, // pre - 0xea: 0x35308, // multiple - 0xeb: 0x16103, // bdi - 0xec: 0x33109, // maxlength - 0xed: 0x7701, // q - 0xee: 0x61b0a, // onauxclick - 0xf0: 0x57003, // wbr - 0xf2: 0x11504, // base - 0xf3: 0x6dd06, // option - 0xf5: 0x40710, // ondurationchange - 0xf7: 0x5508, // noframes - 0xf9: 0x3f908, // dropzone - 0xfb: 0x67105, // scope - 0xfc: 0x9c08, // reversed - 0xfd: 0x3ae0b, // ondragenter - 0xfe: 0x3ee05, // start - 0xff: 0xf903, // xmp - 0x100: 0x5f507, // srclang - 0x101: 0x2ef03, // img + 0xc3: 0x22608, // fieldset + 0xc4: 0x2900d, // typemustmatch + 0xc5: 0xa208, // nomodule + 0xc6: 0x6c07, // noembed + 0xc7: 0x69e0d, // onbeforeprint + 0xc8: 0x19106, // button + 0xc9: 0x2f507, // onclick + 0xca: 0x70407, // summary + 0xcd: 0xfb04, // ruby + 0xce: 0x56405, // class + 0xcf: 0x3f40b, // ondragstart + 0xd0: 0x23107, // caption + 0xd4: 0xdd0e, // allowusermedia + 0xd5: 0x4cf0b, // onloadstart + 0xd9: 0x16b03, // div + 0xda: 0x4a904, // list + 0xdb: 0x32e04, // math + 0xdc: 0x44b05, // input + 0xdf: 0x3ea0a, // ondragover + 0xe0: 0x2de02, // h2 + 0xe2: 0x1b209, // plaintext + 0xe4: 0x4f30c, // onmouseenter + 0xe7: 0x47907, // checked + 0xe8: 0x47003, // pre + 0xea: 0x35f08, // multiple + 0xeb: 0xba03, // bdi + 0xec: 0x33d09, // maxlength + 0xed: 0xcf01, // q + 0xee: 0x61f0a, // onauxclick + 0xf0: 0x57c03, // wbr + 0xf2: 0x3b04, // base + 0xf3: 0x6e306, // option + 0xf5: 0x41310, // ondurationchange + 0xf7: 0x8908, // noframes + 0xf9: 0x40508, // dropzone + 0xfb: 0x67505, // scope + 0xfc: 0x8008, // reversed + 0xfd: 0x3ba0b, // ondragenter + 0xfe: 0x3fa05, // start + 0xff: 0x12f03, // xmp + 0x100: 0x5f907, // srclang + 0x101: 0x30703, // img 0x104: 0x101, // b - 0x105: 0x23c03, // for - 0x106: 0xc105, // aside - 0x107: 0x43d07, // oninput - 0x108: 0x34a04, // area - 0x109: 0x28c0a, // formmethod - 0x10a: 0x72004, // wrap - 0x10c: 0x22402, // rp - 0x10d: 0x45f0a, // onkeypress - 0x10e: 0x5102, // tt - 0x110: 0x33b02, // mi - 0x111: 0x35b05, // muted - 0x112: 0xb003, // alt - 0x113: 0x19004, // code - 0x114: 0x4202, // em - 0x115: 0x3b90a, // ondragexit - 0x117: 0x3d04, // span - 0x119: 0x30f08, // manifest - 0x11a: 0x37b08, // menuitem - 0x11b: 0x57f07, // content - 0x11d: 0x6bd09, // onwaiting - 0x11f: 0x4ba09, // onloadend - 0x121: 0x3720d, // oncontextmenu - 0x123: 0x5c206, // onblur - 0x124: 0x3f007, // article - 0x125: 0xa303, // dir - 0x126: 0xe704, // ping - 0x127: 0x23408, // required - 0x128: 0x44909, // oninvalid - 0x129: 0x6d405, // align - 0x12b: 0x57e04, // icon - 0x12c: 0x64902, // h6 - 0x12d: 0x1b404, // cols - 0x12e: 0x2160a, // figcaption - 0x12f: 0x45209, // onkeydown - 0x130: 0x66708, // onsubmit - 0x131: 0x13609, // oncanplay - 0x132: 0x70503, // sup + 0x105: 0x25403, // for + 0x106: 0x10705, // aside + 0x107: 0x44907, // oninput + 0x108: 0x35604, // area + 0x109: 0x2a40a, // formmethod + 0x10a: 0x72604, // wrap + 0x10c: 0x23c02, // rp + 0x10d: 0x46b0a, // onkeypress + 0x10e: 0x6802, // tt + 0x110: 0x34702, // mi + 0x111: 0x36705, // muted + 0x112: 0xf303, // alt + 0x113: 0x5c504, // code + 0x114: 0x6e02, // em + 0x115: 0x3c50a, // ondragexit + 0x117: 0x9f04, // span + 0x119: 0x6d708, // manifest + 0x11a: 0x38708, // menuitem + 0x11b: 0x58b07, // content + 0x11d: 0x6c109, // onwaiting + 0x11f: 0x4c609, // onloadend + 0x121: 0x37e0d, // oncontextmenu + 0x123: 0x56d06, // onblur + 0x124: 0x3fc07, // article + 0x125: 0x9303, // dir + 0x126: 0xef04, // ping + 0x127: 0x24c08, // required + 0x128: 0x45509, // oninvalid + 0x129: 0xb105, // align + 0x12b: 0x58a04, // icon + 0x12c: 0x64d02, // h6 + 0x12d: 0x1c404, // cols + 0x12e: 0x22e0a, // figcaption + 0x12f: 0x45e09, // onkeydown + 0x130: 0x66b08, // onsubmit + 0x131: 0x14d09, // oncanplay + 0x132: 0x70b03, // sup 0x133: 0xc01, // p - 0x135: 0x3fe09, // onemptied - 0x136: 0x38506, // oncopy - 0x137: 0x55804, // cite - 0x138: 0x39b0a, // ondblclick - 0x13a: 0x4ff0b, // onmousemove - 0x13c: 0x66903, // sub - 0x13d: 0x47b03, // rel - 0x13e: 0xe008, // optgroup - 0x142: 0x3a07, // rowspan - 0x143: 0x36c06, // source - 0x144: 0x1fe08, // noscript - 0x145: 0x55f04, // open - 0x146: 0x1ec03, // ins - 0x147: 0x23c0d, // foreignObject - 0x148: 0x5a10a, // onpopstate - 0x14a: 0x27507, // enctype - 0x14b: 0x25e0e, // onautocomplete - 0x14c: 0x34608, // textarea - 0x14e: 0x2600c, // autocomplete - 0x14f: 0x14002, // hr - 0x150: 0x1ce08, // controls - 0x151: 0xc302, // id - 0x153: 0x21e0c, // onafterprint - 0x155: 0x2490d, // foreignobject - 0x156: 0x31b07, // marquee - 0x157: 0x58e07, // onpause - 0x158: 0x5e202, // dl - 0x159: 0x12c06, // height - 0x15a: 0x33b03, // min - 0x15b: 0xa307, // dirname - 0x15c: 0x1a609, // translate - 0x15d: 0x13004, // html - 0x15e: 0x33b09, // minlength - 0x15f: 0x47a07, // preload - 0x160: 0x70e08, // template - 0x161: 0x3d30b, // ondragleave - 0x164: 0x5b403, // src - 0x165: 0x31506, // strong - 0x167: 0x4c04, // samp - 0x168: 0x6ed07, // address - 0x169: 0x54508, // ononline - 0x16b: 0xfb0b, // placeholder - 0x16c: 0x2ac06, // target - 0x16d: 0x1ee05, // small - 0x16e: 0x6c607, // onwheel - 0x16f: 0x1b90a, // annotation - 0x170: 0x4680a, // spellcheck - 0x171: 0x4607, // details - 0x172: 0xbd06, // canvas - 0x173: 0xeb09, // autofocus + 0x135: 0x40a09, // onemptied + 0x136: 0x39106, // oncopy + 0x137: 0x19c04, // cite + 0x138: 0x3a70a, // ondblclick + 0x13a: 0x50b0b, // onmousemove + 0x13c: 0x66d03, // sub + 0x13d: 0x48703, // rel + 0x13e: 0x5f08, // optgroup + 0x142: 0x9c07, // rowspan + 0x143: 0x37806, // source + 0x144: 0x21608, // noscript + 0x145: 0x1a304, // open + 0x146: 0x20403, // ins + 0x147: 0x2540d, // foreignObject + 0x148: 0x5ad0a, // onpopstate + 0x14a: 0x28d07, // enctype + 0x14b: 0x2760e, // onautocomplete + 0x14c: 0x35208, // textarea + 0x14e: 0x2780c, // autocomplete + 0x14f: 0x15702, // hr + 0x150: 0x1de08, // controls + 0x151: 0x10902, // id + 0x153: 0x2360c, // onafterprint + 0x155: 0x2610d, // foreignobject + 0x156: 0x32707, // marquee + 0x157: 0x59a07, // onpause + 0x158: 0x5e602, // dl + 0x159: 0x5206, // height + 0x15a: 0x34703, // min + 0x15b: 0x9307, // dirname + 0x15c: 0x1f209, // translate + 0x15d: 0x5604, // html + 0x15e: 0x34709, // minlength + 0x15f: 0x48607, // preload + 0x160: 0x71408, // template + 0x161: 0x3df0b, // ondragleave + 0x162: 0x3a02, // rb + 0x164: 0x5c003, // src + 0x165: 0x6dd06, // strong + 0x167: 0x7804, // samp + 0x168: 0x6f307, // address + 0x169: 0x55108, // ononline + 0x16b: 0x1310b, // placeholder + 0x16c: 0x2c406, // target + 0x16d: 0x20605, // small + 0x16e: 0x6ca07, // onwheel + 0x16f: 0x1c90a, // annotation + 0x170: 0x4740a, // spellcheck + 0x171: 0x7207, // details + 0x172: 0x10306, // canvas + 0x173: 0x12109, // autofocus 0x174: 0xc05, // param - 0x176: 0x45708, // download - 0x177: 0x44603, // del - 0x178: 0x36007, // onclose - 0x179: 0x16003, // kbd - 0x17a: 0x30106, // applet - 0x17b: 0x2c804, // href - 0x17c: 0x5ed08, // onresize - 0x17e: 0x4910c, // onloadeddata - 0x180: 0x7402, // tr - 0x181: 0x2a80a, // formtarget - 0x182: 0xca05, // title - 0x183: 0x6f905, // style - 0x184: 0x7a06, // strike - 0x185: 0x59206, // usemap - 0x186: 0x2e406, // iframe + 0x176: 0x46308, // download + 0x177: 0x45203, // del + 0x178: 0x36c07, // onclose + 0x179: 0xb903, // kbd + 0x17a: 0x31906, // applet + 0x17b: 0x2e004, // href + 0x17c: 0x5f108, // onresize + 0x17e: 0x49d0c, // onloadeddata + 0x180: 0xcc02, // tr + 0x181: 0x2c00a, // formtarget + 0x182: 0x11005, // title + 0x183: 0x6ff05, // style + 0x184: 0xd206, // strike + 0x185: 0x59e06, // usemap + 0x186: 0x2fc06, // iframe 0x187: 0x1004, // main - 0x189: 0x9707, // picture - 0x18c: 0x2fe05, // ismap - 0x18e: 0x49904, // data - 0x18f: 0xda05, // label - 0x191: 0x3c50e, // referrerpolicy - 0x192: 0x13f02, // th - 0x194: 0x52a06, // prompt - 0x195: 0x5bd07, // section - 0x197: 0x6cd07, // optimum - 0x198: 0x2c304, // high - 0x199: 0x14502, // h1 - 0x19a: 0x65509, // onstalled - 0x19b: 0x15603, // var - 0x19c: 0x11c04, // time - 0x19e: 0x67002, // ms - 0x19f: 0x32506, // header - 0x1a0: 0x4ce09, // onmessage - 0x1a1: 0x56205, // nonce - 0x1a2: 0x2560a, // formaction - 0x1a3: 0x20806, // center + 0x189: 0x7b07, // picture + 0x18c: 0x31605, // ismap + 0x18e: 0x4a504, // data + 0x18f: 0x5905, // label + 0x191: 0x3d10e, // referrerpolicy + 0x192: 0x15602, // th + 0x194: 0x53606, // prompt + 0x195: 0x56807, // section + 0x197: 0x6d107, // optimum + 0x198: 0x2db04, // high + 0x199: 0x15c02, // h1 + 0x19a: 0x65909, // onstalled + 0x19b: 0x16d03, // var + 0x19c: 0x4204, // time + 0x19e: 0x67402, // ms + 0x19f: 0x33106, // header + 0x1a0: 0x4da09, // onmessage + 0x1a1: 0x1a605, // nonce + 0x1a2: 0x26e0a, // formaction + 0x1a3: 0x22006, // center 0x1a4: 0x3704, // nobr - 0x1a5: 0x58905, // table - 0x1a6: 0x49d07, // listing - 0x1a7: 0x18a06, // legend - 0x1a9: 0x28309, // challenge - 0x1aa: 0x23006, // figure - 0x1ab: 0x8e05, // media - 0x1ae: 0x8104, // type - 0x1af: 0x11904, // font - 0x1b0: 0x4ce0e, // onmessageerror - 0x1b1: 0x36508, // seamless - 0x1b2: 0x5f03, // dfn - 0x1b3: 0x19205, // defer - 0x1b4: 0x6b03, // low - 0x1b5: 0x62d09, // onseeking - 0x1b6: 0x5170b, // onmouseover - 0x1b7: 0x29a0a, // novalidate - 0x1b8: 0x7160a, // workertype - 0x1ba: 0x3c107, // itemref + 0x1a5: 0x59505, // table + 0x1a6: 0x4a907, // listing + 0x1a7: 0x18106, // legend + 0x1a9: 0x29b09, // challenge + 0x1aa: 0x24806, // figure + 0x1ab: 0xe605, // media + 0x1ae: 0xd904, // type + 0x1af: 0x3f04, // font + 0x1b0: 0x4da0e, // onmessageerror + 0x1b1: 0x37108, // seamless + 0x1b2: 0x8703, // dfn + 0x1b3: 0x5c705, // defer + 0x1b4: 0xc303, // low + 0x1b5: 0x19a03, // rtc + 0x1b6: 0x5230b, // onmouseover + 0x1b7: 0x2b20a, // novalidate + 0x1b8: 0x71c0a, // workertype + 0x1ba: 0x3cd07, // itemref 0x1bd: 0x1, // a - 0x1be: 0x30003, // map - 0x1bf: 0x11a0c, // ontimeupdate - 0x1c0: 0x14707, // bgsound + 0x1be: 0x31803, // map + 0x1bf: 0x400c, // ontimeupdate + 0x1c0: 0x15e07, // bgsound 0x1c1: 0x3206, // keygen 0x1c2: 0x2705, // tbody - 0x1c5: 0x64006, // onshow + 0x1c5: 0x64406, // onshow 0x1c7: 0x2501, // s - 0x1c8: 0x4f07, // pattern - 0x1cc: 0x13610, // oncanplaythrough - 0x1ce: 0x2bf02, // dd - 0x1cf: 0x6f306, // srcset - 0x1d0: 0x15903, // big - 0x1d2: 0x64d08, // sortable - 0x1d3: 0x47407, // onkeyup - 0x1d5: 0x59806, // onplay - 0x1d7: 0x4ac04, // meta - 0x1d8: 0x3f706, // ondrop - 0x1da: 0x5fc08, // onscroll - 0x1db: 0x1e30b, // crossorigin - 0x1dc: 0x5670a, // onpageshow + 0x1c8: 0x6607, // pattern + 0x1cc: 0x14d10, // oncanplaythrough + 0x1ce: 0x2d702, // dd + 0x1cf: 0x6f906, // srcset + 0x1d0: 0x17003, // big + 0x1d2: 0x65108, // sortable + 0x1d3: 0x48007, // onkeyup + 0x1d5: 0x5a406, // onplay + 0x1d7: 0x4b804, // meta + 0x1d8: 0x40306, // ondrop + 0x1da: 0x60008, // onscroll + 0x1db: 0x1fb0b, // crossorigin + 0x1dc: 0x5730a, // onpageshow 0x1dd: 0x4, // abbr - 0x1de: 0x5e02, // td - 0x1df: 0x57f0f, // contenteditable - 0x1e0: 0x25a06, // action - 0x1e1: 0x10a0b, // playsinline - 0x1e2: 0x42507, // onfocus - 0x1e3: 0x2c808, // hreflang - 0x1e5: 0x50a0a, // onmouseout - 0x1e6: 0x5e607, // onreset - 0x1e7: 0x10608, // autoplay - 0x1ea: 0x67106, // scoped + 0x1de: 0x9202, // td + 0x1df: 0x58b0f, // contenteditable + 0x1e0: 0x27206, // action + 0x1e1: 0x1400b, // playsinline + 0x1e2: 0x43107, // onfocus + 0x1e3: 0x2e008, // hreflang + 0x1e5: 0x5160a, // onmouseout + 0x1e6: 0x5ea07, // onreset + 0x1e7: 0x13c08, // autoplay + 0x1e8: 0x63109, // onseeking + 0x1ea: 0x67506, // scoped 0x1ec: 0x30a, // radiogroup - 0x1ee: 0x3740b, // contextmenu - 0x1ef: 0x52209, // onmouseup - 0x1f1: 0x2b206, // hgroup - 0x1f2: 0x1f00f, // allowfullscreen - 0x1f3: 0x4b208, // tabindex - 0x1f6: 0x2f707, // isindex + 0x1ee: 0x3800b, // contextmenu + 0x1ef: 0x52e09, // onmouseup + 0x1f1: 0x2ca06, // hgroup + 0x1f2: 0x2080f, // allowfullscreen + 0x1f3: 0x4be08, // tabindex + 0x1f6: 0x30f07, // isindex 0x1f7: 0x1a0e, // accept-charset - 0x1f8: 0x2960e, // formnovalidate - 0x1fb: 0x1b90e, // annotation-xml - 0x1fc: 0x4205, // embed - 0x1fd: 0x20006, // script - 0x1fe: 0x16206, // dialog - 0x1ff: 0x1c707, // command + 0x1f8: 0x2ae0e, // formnovalidate + 0x1fb: 0x1c90e, // annotation-xml + 0x1fc: 0x6e05, // embed + 0x1fd: 0x21806, // script + 0x1fe: 0xbb06, // dialog + 0x1ff: 0x1d707, // command } -const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" + - "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" + - "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" + - "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" + - "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" + - "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" + - "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" + - "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" + - "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" + - "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" + - "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" + - "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" + - "http-equivideonclickiframeimageimglyph3isindexismappletitemt" + - "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" + - "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" + - "doncopyoncuechangeoncutondblclickondragendondragenterondrage" + - "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" + - "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" + - "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" + - "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" + - "databindexonloadendonloadstartonmessageerroronmousedownonmou" + - "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" + - "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" + - "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" + - "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" + - "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" + - "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" + - "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" + - "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" + - "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" + - "svgsystemplateworkertypewrap" +const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" + + "asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" + + "sampictureversedfnoframesetdirnameterowspanomoduleacronymali" + + "gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" + + "ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" + + "dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" + + "bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" + + "penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" + + "ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" + + "ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" + + "ignObjectforeignobjectformactionautocompleteerrorformenctype" + + "mustmatchallengeformmethodformnovalidatetimeformtargethgroup" + + "osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" + + "ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" + + "inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" + + "extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" + + "enterondragexitemreferrerpolicyondragleaveondragoverondragst" + + "articleondropzonemptiedondurationchangeonendedonerroronfocus" + + "paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" + + "spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" + + "onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" + + "usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" + + "seoveronmouseupromptonmousewheelonofflineononlineonpagehides" + + "classectionbluronpageshowbronpastepublicontenteditableonpaus" + + "emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" + + "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" + + "violationauxclickonseekedonseekingonselectedonshowidth6onsor" + + "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" + + "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" + + "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" + + "arysupsvgsystemplateworkertypewrap" diff --git a/vendor/golang.org/x/net/html/atom/table_test.go b/vendor/golang.org/x/net/html/atom/table_test.go index 1689105..8a30762 100644 --- a/vendor/golang.org/x/net/html/atom/table_test.go +++ b/vendor/golang.org/x/net/html/atom/table_test.go @@ -10,6 +10,7 @@ var testAtomList = []string{ "accept", "accept-charset", "accesskey", + "acronym", "action", "address", "align", @@ -295,6 +296,7 @@ var testAtomList = []string{ "public", "q", "radiogroup", + "rb", "readonly", "referrerpolicy", "rel", @@ -304,6 +306,7 @@ var testAtomList = []string{ "rowspan", "rp", "rt", + "rtc", "ruby", "s", "samp", diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go index b37e621..5eb7c5a 100644 --- a/vendor/golang.org/x/net/html/const.go +++ b/vendor/golang.org/x/net/html/const.go @@ -4,7 +4,7 @@ package html -// Section 12.2.3.2 of the HTML5 specification says "The following elements +// Section 12.2.4.2 of the HTML5 specification says "The following elements // have varying levels of special parsing rules". // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements var isSpecialElementMap = map[string]bool{ diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go index a50c04c..b628880 100644 --- a/vendor/golang.org/x/net/html/entity.go +++ b/vendor/golang.org/x/net/html/entity.go @@ -75,2083 +75,2083 @@ var entity = map[string]rune{ "Copf;": '\U00002102', "Coproduct;": '\U00002210', "CounterClockwiseContourIntegral;": '\U00002233', - "Cross;": '\U00002A2F', - "Cscr;": '\U0001D49E', - "Cup;": '\U000022D3', - "CupCap;": '\U0000224D', - "DD;": '\U00002145', - "DDotrahd;": '\U00002911', - "DJcy;": '\U00000402', - "DScy;": '\U00000405', - "DZcy;": '\U0000040F', - "Dagger;": '\U00002021', - "Darr;": '\U000021A1', - "Dashv;": '\U00002AE4', - "Dcaron;": '\U0000010E', - "Dcy;": '\U00000414', - "Del;": '\U00002207', - "Delta;": '\U00000394', - "Dfr;": '\U0001D507', - "DiacriticalAcute;": '\U000000B4', - "DiacriticalDot;": '\U000002D9', - "DiacriticalDoubleAcute;": '\U000002DD', - "DiacriticalGrave;": '\U00000060', - "DiacriticalTilde;": '\U000002DC', - "Diamond;": '\U000022C4', - "DifferentialD;": '\U00002146', - "Dopf;": '\U0001D53B', - "Dot;": '\U000000A8', - "DotDot;": '\U000020DC', - "DotEqual;": '\U00002250', - "DoubleContourIntegral;": '\U0000222F', - "DoubleDot;": '\U000000A8', - "DoubleDownArrow;": '\U000021D3', - "DoubleLeftArrow;": '\U000021D0', - "DoubleLeftRightArrow;": '\U000021D4', - "DoubleLeftTee;": '\U00002AE4', - "DoubleLongLeftArrow;": '\U000027F8', - "DoubleLongLeftRightArrow;": '\U000027FA', - "DoubleLongRightArrow;": '\U000027F9', - "DoubleRightArrow;": '\U000021D2', - "DoubleRightTee;": '\U000022A8', - "DoubleUpArrow;": '\U000021D1', - "DoubleUpDownArrow;": '\U000021D5', - "DoubleVerticalBar;": '\U00002225', - "DownArrow;": '\U00002193', - "DownArrowBar;": '\U00002913', - "DownArrowUpArrow;": '\U000021F5', - "DownBreve;": '\U00000311', - "DownLeftRightVector;": '\U00002950', - "DownLeftTeeVector;": '\U0000295E', - "DownLeftVector;": '\U000021BD', - "DownLeftVectorBar;": '\U00002956', - "DownRightTeeVector;": '\U0000295F', - "DownRightVector;": '\U000021C1', - "DownRightVectorBar;": '\U00002957', - "DownTee;": '\U000022A4', - "DownTeeArrow;": '\U000021A7', - "Downarrow;": '\U000021D3', - "Dscr;": '\U0001D49F', - "Dstrok;": '\U00000110', - "ENG;": '\U0000014A', - "ETH;": '\U000000D0', - "Eacute;": '\U000000C9', - "Ecaron;": '\U0000011A', - "Ecirc;": '\U000000CA', - "Ecy;": '\U0000042D', - "Edot;": '\U00000116', - "Efr;": '\U0001D508', - "Egrave;": '\U000000C8', - "Element;": '\U00002208', - "Emacr;": '\U00000112', - "EmptySmallSquare;": '\U000025FB', - "EmptyVerySmallSquare;": '\U000025AB', - "Eogon;": '\U00000118', - "Eopf;": '\U0001D53C', - "Epsilon;": '\U00000395', - "Equal;": '\U00002A75', - "EqualTilde;": '\U00002242', - "Equilibrium;": '\U000021CC', - "Escr;": '\U00002130', - "Esim;": '\U00002A73', - "Eta;": '\U00000397', - "Euml;": '\U000000CB', - "Exists;": '\U00002203', - "ExponentialE;": '\U00002147', - "Fcy;": '\U00000424', - "Ffr;": '\U0001D509', - "FilledSmallSquare;": '\U000025FC', - "FilledVerySmallSquare;": '\U000025AA', - "Fopf;": '\U0001D53D', - "ForAll;": '\U00002200', - "Fouriertrf;": '\U00002131', - "Fscr;": '\U00002131', - "GJcy;": '\U00000403', - "GT;": '\U0000003E', - "Gamma;": '\U00000393', - "Gammad;": '\U000003DC', - "Gbreve;": '\U0000011E', - "Gcedil;": '\U00000122', - "Gcirc;": '\U0000011C', - "Gcy;": '\U00000413', - "Gdot;": '\U00000120', - "Gfr;": '\U0001D50A', - "Gg;": '\U000022D9', - "Gopf;": '\U0001D53E', - "GreaterEqual;": '\U00002265', - "GreaterEqualLess;": '\U000022DB', - "GreaterFullEqual;": '\U00002267', - "GreaterGreater;": '\U00002AA2', - "GreaterLess;": '\U00002277', - "GreaterSlantEqual;": '\U00002A7E', - "GreaterTilde;": '\U00002273', - "Gscr;": '\U0001D4A2', - "Gt;": '\U0000226B', - "HARDcy;": '\U0000042A', - "Hacek;": '\U000002C7', - "Hat;": '\U0000005E', - "Hcirc;": '\U00000124', - "Hfr;": '\U0000210C', - "HilbertSpace;": '\U0000210B', - "Hopf;": '\U0000210D', - "HorizontalLine;": '\U00002500', - "Hscr;": '\U0000210B', - "Hstrok;": '\U00000126', - "HumpDownHump;": '\U0000224E', - "HumpEqual;": '\U0000224F', - "IEcy;": '\U00000415', - "IJlig;": '\U00000132', - "IOcy;": '\U00000401', - "Iacute;": '\U000000CD', - "Icirc;": '\U000000CE', - "Icy;": '\U00000418', - "Idot;": '\U00000130', - "Ifr;": '\U00002111', - "Igrave;": '\U000000CC', - "Im;": '\U00002111', - "Imacr;": '\U0000012A', - "ImaginaryI;": '\U00002148', - "Implies;": '\U000021D2', - "Int;": '\U0000222C', - "Integral;": '\U0000222B', - "Intersection;": '\U000022C2', - "InvisibleComma;": '\U00002063', - "InvisibleTimes;": '\U00002062', - "Iogon;": '\U0000012E', - "Iopf;": '\U0001D540', - "Iota;": '\U00000399', - "Iscr;": '\U00002110', - "Itilde;": '\U00000128', - "Iukcy;": '\U00000406', - "Iuml;": '\U000000CF', - "Jcirc;": '\U00000134', - "Jcy;": '\U00000419', - "Jfr;": '\U0001D50D', - "Jopf;": '\U0001D541', - "Jscr;": '\U0001D4A5', - "Jsercy;": '\U00000408', - "Jukcy;": '\U00000404', - "KHcy;": '\U00000425', - "KJcy;": '\U0000040C', - "Kappa;": '\U0000039A', - "Kcedil;": '\U00000136', - "Kcy;": '\U0000041A', - "Kfr;": '\U0001D50E', - "Kopf;": '\U0001D542', - "Kscr;": '\U0001D4A6', - "LJcy;": '\U00000409', - "LT;": '\U0000003C', - "Lacute;": '\U00000139', - "Lambda;": '\U0000039B', - "Lang;": '\U000027EA', - "Laplacetrf;": '\U00002112', - "Larr;": '\U0000219E', - "Lcaron;": '\U0000013D', - "Lcedil;": '\U0000013B', - "Lcy;": '\U0000041B', - "LeftAngleBracket;": '\U000027E8', - "LeftArrow;": '\U00002190', - "LeftArrowBar;": '\U000021E4', - "LeftArrowRightArrow;": '\U000021C6', - "LeftCeiling;": '\U00002308', - "LeftDoubleBracket;": '\U000027E6', - "LeftDownTeeVector;": '\U00002961', - "LeftDownVector;": '\U000021C3', - "LeftDownVectorBar;": '\U00002959', - "LeftFloor;": '\U0000230A', - "LeftRightArrow;": '\U00002194', - "LeftRightVector;": '\U0000294E', - "LeftTee;": '\U000022A3', - "LeftTeeArrow;": '\U000021A4', - "LeftTeeVector;": '\U0000295A', - "LeftTriangle;": '\U000022B2', - "LeftTriangleBar;": '\U000029CF', - "LeftTriangleEqual;": '\U000022B4', - "LeftUpDownVector;": '\U00002951', - "LeftUpTeeVector;": '\U00002960', - "LeftUpVector;": '\U000021BF', - "LeftUpVectorBar;": '\U00002958', - "LeftVector;": '\U000021BC', - "LeftVectorBar;": '\U00002952', - "Leftarrow;": '\U000021D0', - "Leftrightarrow;": '\U000021D4', - "LessEqualGreater;": '\U000022DA', - "LessFullEqual;": '\U00002266', - "LessGreater;": '\U00002276', - "LessLess;": '\U00002AA1', - "LessSlantEqual;": '\U00002A7D', - "LessTilde;": '\U00002272', - "Lfr;": '\U0001D50F', - "Ll;": '\U000022D8', - "Lleftarrow;": '\U000021DA', - "Lmidot;": '\U0000013F', - "LongLeftArrow;": '\U000027F5', - "LongLeftRightArrow;": '\U000027F7', - "LongRightArrow;": '\U000027F6', - "Longleftarrow;": '\U000027F8', - "Longleftrightarrow;": '\U000027FA', - "Longrightarrow;": '\U000027F9', - "Lopf;": '\U0001D543', - "LowerLeftArrow;": '\U00002199', - "LowerRightArrow;": '\U00002198', - "Lscr;": '\U00002112', - "Lsh;": '\U000021B0', - "Lstrok;": '\U00000141', - "Lt;": '\U0000226A', - "Map;": '\U00002905', - "Mcy;": '\U0000041C', - "MediumSpace;": '\U0000205F', - "Mellintrf;": '\U00002133', - "Mfr;": '\U0001D510', - "MinusPlus;": '\U00002213', - "Mopf;": '\U0001D544', - "Mscr;": '\U00002133', - "Mu;": '\U0000039C', - "NJcy;": '\U0000040A', - "Nacute;": '\U00000143', - "Ncaron;": '\U00000147', - "Ncedil;": '\U00000145', - "Ncy;": '\U0000041D', - "NegativeMediumSpace;": '\U0000200B', - "NegativeThickSpace;": '\U0000200B', - "NegativeThinSpace;": '\U0000200B', - "NegativeVeryThinSpace;": '\U0000200B', - "NestedGreaterGreater;": '\U0000226B', - "NestedLessLess;": '\U0000226A', - "NewLine;": '\U0000000A', - "Nfr;": '\U0001D511', - "NoBreak;": '\U00002060', - "NonBreakingSpace;": '\U000000A0', - "Nopf;": '\U00002115', - "Not;": '\U00002AEC', - "NotCongruent;": '\U00002262', - "NotCupCap;": '\U0000226D', - "NotDoubleVerticalBar;": '\U00002226', - "NotElement;": '\U00002209', - "NotEqual;": '\U00002260', - "NotExists;": '\U00002204', - "NotGreater;": '\U0000226F', - "NotGreaterEqual;": '\U00002271', - "NotGreaterLess;": '\U00002279', - "NotGreaterTilde;": '\U00002275', - "NotLeftTriangle;": '\U000022EA', - "NotLeftTriangleEqual;": '\U000022EC', - "NotLess;": '\U0000226E', - "NotLessEqual;": '\U00002270', - "NotLessGreater;": '\U00002278', - "NotLessTilde;": '\U00002274', - "NotPrecedes;": '\U00002280', - "NotPrecedesSlantEqual;": '\U000022E0', - "NotReverseElement;": '\U0000220C', - "NotRightTriangle;": '\U000022EB', - "NotRightTriangleEqual;": '\U000022ED', - "NotSquareSubsetEqual;": '\U000022E2', - "NotSquareSupersetEqual;": '\U000022E3', - "NotSubsetEqual;": '\U00002288', - "NotSucceeds;": '\U00002281', - "NotSucceedsSlantEqual;": '\U000022E1', - "NotSupersetEqual;": '\U00002289', - "NotTilde;": '\U00002241', - "NotTildeEqual;": '\U00002244', - "NotTildeFullEqual;": '\U00002247', - "NotTildeTilde;": '\U00002249', - "NotVerticalBar;": '\U00002224', - "Nscr;": '\U0001D4A9', - "Ntilde;": '\U000000D1', - "Nu;": '\U0000039D', - "OElig;": '\U00000152', - "Oacute;": '\U000000D3', - "Ocirc;": '\U000000D4', - "Ocy;": '\U0000041E', - "Odblac;": '\U00000150', - "Ofr;": '\U0001D512', - "Ograve;": '\U000000D2', - "Omacr;": '\U0000014C', - "Omega;": '\U000003A9', - "Omicron;": '\U0000039F', - "Oopf;": '\U0001D546', - "OpenCurlyDoubleQuote;": '\U0000201C', - "OpenCurlyQuote;": '\U00002018', - "Or;": '\U00002A54', - "Oscr;": '\U0001D4AA', - "Oslash;": '\U000000D8', - "Otilde;": '\U000000D5', - "Otimes;": '\U00002A37', - "Ouml;": '\U000000D6', - "OverBar;": '\U0000203E', - "OverBrace;": '\U000023DE', - "OverBracket;": '\U000023B4', - "OverParenthesis;": '\U000023DC', - "PartialD;": '\U00002202', - "Pcy;": '\U0000041F', - "Pfr;": '\U0001D513', - "Phi;": '\U000003A6', - "Pi;": '\U000003A0', - "PlusMinus;": '\U000000B1', - "Poincareplane;": '\U0000210C', - "Popf;": '\U00002119', - "Pr;": '\U00002ABB', - "Precedes;": '\U0000227A', - "PrecedesEqual;": '\U00002AAF', - "PrecedesSlantEqual;": '\U0000227C', - "PrecedesTilde;": '\U0000227E', - "Prime;": '\U00002033', - "Product;": '\U0000220F', - "Proportion;": '\U00002237', - "Proportional;": '\U0000221D', - "Pscr;": '\U0001D4AB', - "Psi;": '\U000003A8', - "QUOT;": '\U00000022', - "Qfr;": '\U0001D514', - "Qopf;": '\U0000211A', - "Qscr;": '\U0001D4AC', - "RBarr;": '\U00002910', - "REG;": '\U000000AE', - "Racute;": '\U00000154', - "Rang;": '\U000027EB', - "Rarr;": '\U000021A0', - "Rarrtl;": '\U00002916', - "Rcaron;": '\U00000158', - "Rcedil;": '\U00000156', - "Rcy;": '\U00000420', - "Re;": '\U0000211C', - "ReverseElement;": '\U0000220B', - "ReverseEquilibrium;": '\U000021CB', - "ReverseUpEquilibrium;": '\U0000296F', - "Rfr;": '\U0000211C', - "Rho;": '\U000003A1', - "RightAngleBracket;": '\U000027E9', - "RightArrow;": '\U00002192', - "RightArrowBar;": '\U000021E5', - "RightArrowLeftArrow;": '\U000021C4', - "RightCeiling;": '\U00002309', - "RightDoubleBracket;": '\U000027E7', - "RightDownTeeVector;": '\U0000295D', - "RightDownVector;": '\U000021C2', - "RightDownVectorBar;": '\U00002955', - "RightFloor;": '\U0000230B', - "RightTee;": '\U000022A2', - "RightTeeArrow;": '\U000021A6', - "RightTeeVector;": '\U0000295B', - "RightTriangle;": '\U000022B3', - "RightTriangleBar;": '\U000029D0', - "RightTriangleEqual;": '\U000022B5', - "RightUpDownVector;": '\U0000294F', - "RightUpTeeVector;": '\U0000295C', - "RightUpVector;": '\U000021BE', - "RightUpVectorBar;": '\U00002954', - "RightVector;": '\U000021C0', - "RightVectorBar;": '\U00002953', - "Rightarrow;": '\U000021D2', - "Ropf;": '\U0000211D', - "RoundImplies;": '\U00002970', - "Rrightarrow;": '\U000021DB', - "Rscr;": '\U0000211B', - "Rsh;": '\U000021B1', - "RuleDelayed;": '\U000029F4', - "SHCHcy;": '\U00000429', - "SHcy;": '\U00000428', - "SOFTcy;": '\U0000042C', - "Sacute;": '\U0000015A', - "Sc;": '\U00002ABC', - "Scaron;": '\U00000160', - "Scedil;": '\U0000015E', - "Scirc;": '\U0000015C', - "Scy;": '\U00000421', - "Sfr;": '\U0001D516', - "ShortDownArrow;": '\U00002193', - "ShortLeftArrow;": '\U00002190', - "ShortRightArrow;": '\U00002192', - "ShortUpArrow;": '\U00002191', - "Sigma;": '\U000003A3', - "SmallCircle;": '\U00002218', - "Sopf;": '\U0001D54A', - "Sqrt;": '\U0000221A', - "Square;": '\U000025A1', - "SquareIntersection;": '\U00002293', - "SquareSubset;": '\U0000228F', - "SquareSubsetEqual;": '\U00002291', - "SquareSuperset;": '\U00002290', - "SquareSupersetEqual;": '\U00002292', - "SquareUnion;": '\U00002294', - "Sscr;": '\U0001D4AE', - "Star;": '\U000022C6', - "Sub;": '\U000022D0', - "Subset;": '\U000022D0', - "SubsetEqual;": '\U00002286', - "Succeeds;": '\U0000227B', - "SucceedsEqual;": '\U00002AB0', - "SucceedsSlantEqual;": '\U0000227D', - "SucceedsTilde;": '\U0000227F', - "SuchThat;": '\U0000220B', - "Sum;": '\U00002211', - "Sup;": '\U000022D1', - "Superset;": '\U00002283', - "SupersetEqual;": '\U00002287', - "Supset;": '\U000022D1', - "THORN;": '\U000000DE', - "TRADE;": '\U00002122', - "TSHcy;": '\U0000040B', - "TScy;": '\U00000426', - "Tab;": '\U00000009', - "Tau;": '\U000003A4', - "Tcaron;": '\U00000164', - "Tcedil;": '\U00000162', - "Tcy;": '\U00000422', - "Tfr;": '\U0001D517', - "Therefore;": '\U00002234', - "Theta;": '\U00000398', - "ThinSpace;": '\U00002009', - "Tilde;": '\U0000223C', - "TildeEqual;": '\U00002243', - "TildeFullEqual;": '\U00002245', - "TildeTilde;": '\U00002248', - "Topf;": '\U0001D54B', - "TripleDot;": '\U000020DB', - "Tscr;": '\U0001D4AF', - "Tstrok;": '\U00000166', - "Uacute;": '\U000000DA', - "Uarr;": '\U0000219F', - "Uarrocir;": '\U00002949', - "Ubrcy;": '\U0000040E', - "Ubreve;": '\U0000016C', - "Ucirc;": '\U000000DB', - "Ucy;": '\U00000423', - "Udblac;": '\U00000170', - "Ufr;": '\U0001D518', - "Ugrave;": '\U000000D9', - "Umacr;": '\U0000016A', - "UnderBar;": '\U0000005F', - "UnderBrace;": '\U000023DF', - "UnderBracket;": '\U000023B5', - "UnderParenthesis;": '\U000023DD', - "Union;": '\U000022C3', - "UnionPlus;": '\U0000228E', - "Uogon;": '\U00000172', - "Uopf;": '\U0001D54C', - "UpArrow;": '\U00002191', - "UpArrowBar;": '\U00002912', - "UpArrowDownArrow;": '\U000021C5', - "UpDownArrow;": '\U00002195', - "UpEquilibrium;": '\U0000296E', - "UpTee;": '\U000022A5', - "UpTeeArrow;": '\U000021A5', - "Uparrow;": '\U000021D1', - "Updownarrow;": '\U000021D5', - "UpperLeftArrow;": '\U00002196', - "UpperRightArrow;": '\U00002197', - "Upsi;": '\U000003D2', - "Upsilon;": '\U000003A5', - "Uring;": '\U0000016E', - "Uscr;": '\U0001D4B0', - "Utilde;": '\U00000168', - "Uuml;": '\U000000DC', - "VDash;": '\U000022AB', - "Vbar;": '\U00002AEB', - "Vcy;": '\U00000412', - "Vdash;": '\U000022A9', - "Vdashl;": '\U00002AE6', - "Vee;": '\U000022C1', - "Verbar;": '\U00002016', - "Vert;": '\U00002016', - "VerticalBar;": '\U00002223', - "VerticalLine;": '\U0000007C', - "VerticalSeparator;": '\U00002758', - "VerticalTilde;": '\U00002240', - "VeryThinSpace;": '\U0000200A', - "Vfr;": '\U0001D519', - "Vopf;": '\U0001D54D', - "Vscr;": '\U0001D4B1', - "Vvdash;": '\U000022AA', - "Wcirc;": '\U00000174', - "Wedge;": '\U000022C0', - "Wfr;": '\U0001D51A', - "Wopf;": '\U0001D54E', - "Wscr;": '\U0001D4B2', - "Xfr;": '\U0001D51B', - "Xi;": '\U0000039E', - "Xopf;": '\U0001D54F', - "Xscr;": '\U0001D4B3', - "YAcy;": '\U0000042F', - "YIcy;": '\U00000407', - "YUcy;": '\U0000042E', - "Yacute;": '\U000000DD', - "Ycirc;": '\U00000176', - "Ycy;": '\U0000042B', - "Yfr;": '\U0001D51C', - "Yopf;": '\U0001D550', - "Yscr;": '\U0001D4B4', - "Yuml;": '\U00000178', - "ZHcy;": '\U00000416', - "Zacute;": '\U00000179', - "Zcaron;": '\U0000017D', - "Zcy;": '\U00000417', - "Zdot;": '\U0000017B', - "ZeroWidthSpace;": '\U0000200B', - "Zeta;": '\U00000396', - "Zfr;": '\U00002128', - "Zopf;": '\U00002124', - "Zscr;": '\U0001D4B5', - "aacute;": '\U000000E1', - "abreve;": '\U00000103', - "ac;": '\U0000223E', - "acd;": '\U0000223F', - "acirc;": '\U000000E2', - "acute;": '\U000000B4', - "acy;": '\U00000430', - "aelig;": '\U000000E6', - "af;": '\U00002061', - "afr;": '\U0001D51E', - "agrave;": '\U000000E0', - "alefsym;": '\U00002135', - "aleph;": '\U00002135', - "alpha;": '\U000003B1', - "amacr;": '\U00000101', - "amalg;": '\U00002A3F', - "amp;": '\U00000026', - "and;": '\U00002227', - "andand;": '\U00002A55', - "andd;": '\U00002A5C', - "andslope;": '\U00002A58', - "andv;": '\U00002A5A', - "ang;": '\U00002220', - "ange;": '\U000029A4', - "angle;": '\U00002220', - "angmsd;": '\U00002221', - "angmsdaa;": '\U000029A8', - "angmsdab;": '\U000029A9', - "angmsdac;": '\U000029AA', - "angmsdad;": '\U000029AB', - "angmsdae;": '\U000029AC', - "angmsdaf;": '\U000029AD', - "angmsdag;": '\U000029AE', - "angmsdah;": '\U000029AF', - "angrt;": '\U0000221F', - "angrtvb;": '\U000022BE', - "angrtvbd;": '\U0000299D', - "angsph;": '\U00002222', - "angst;": '\U000000C5', - "angzarr;": '\U0000237C', - "aogon;": '\U00000105', - "aopf;": '\U0001D552', - "ap;": '\U00002248', - "apE;": '\U00002A70', - "apacir;": '\U00002A6F', - "ape;": '\U0000224A', - "apid;": '\U0000224B', - "apos;": '\U00000027', - "approx;": '\U00002248', - "approxeq;": '\U0000224A', - "aring;": '\U000000E5', - "ascr;": '\U0001D4B6', - "ast;": '\U0000002A', - "asymp;": '\U00002248', - "asympeq;": '\U0000224D', - "atilde;": '\U000000E3', - "auml;": '\U000000E4', - "awconint;": '\U00002233', - "awint;": '\U00002A11', - "bNot;": '\U00002AED', - "backcong;": '\U0000224C', - "backepsilon;": '\U000003F6', - "backprime;": '\U00002035', - "backsim;": '\U0000223D', - "backsimeq;": '\U000022CD', - "barvee;": '\U000022BD', - "barwed;": '\U00002305', - "barwedge;": '\U00002305', - "bbrk;": '\U000023B5', - "bbrktbrk;": '\U000023B6', - "bcong;": '\U0000224C', - "bcy;": '\U00000431', - "bdquo;": '\U0000201E', - "becaus;": '\U00002235', - "because;": '\U00002235', - "bemptyv;": '\U000029B0', - "bepsi;": '\U000003F6', - "bernou;": '\U0000212C', - "beta;": '\U000003B2', - "beth;": '\U00002136', - "between;": '\U0000226C', - "bfr;": '\U0001D51F', - "bigcap;": '\U000022C2', - "bigcirc;": '\U000025EF', - "bigcup;": '\U000022C3', - "bigodot;": '\U00002A00', - "bigoplus;": '\U00002A01', - "bigotimes;": '\U00002A02', - "bigsqcup;": '\U00002A06', - "bigstar;": '\U00002605', - "bigtriangledown;": '\U000025BD', - "bigtriangleup;": '\U000025B3', - "biguplus;": '\U00002A04', - "bigvee;": '\U000022C1', - "bigwedge;": '\U000022C0', - "bkarow;": '\U0000290D', - "blacklozenge;": '\U000029EB', - "blacksquare;": '\U000025AA', - "blacktriangle;": '\U000025B4', - "blacktriangledown;": '\U000025BE', - "blacktriangleleft;": '\U000025C2', - "blacktriangleright;": '\U000025B8', - "blank;": '\U00002423', - "blk12;": '\U00002592', - "blk14;": '\U00002591', - "blk34;": '\U00002593', - "block;": '\U00002588', - "bnot;": '\U00002310', - "bopf;": '\U0001D553', - "bot;": '\U000022A5', - "bottom;": '\U000022A5', - "bowtie;": '\U000022C8', - "boxDL;": '\U00002557', - "boxDR;": '\U00002554', - "boxDl;": '\U00002556', - "boxDr;": '\U00002553', - "boxH;": '\U00002550', - "boxHD;": '\U00002566', - "boxHU;": '\U00002569', - "boxHd;": '\U00002564', - "boxHu;": '\U00002567', - "boxUL;": '\U0000255D', - "boxUR;": '\U0000255A', - "boxUl;": '\U0000255C', - "boxUr;": '\U00002559', - "boxV;": '\U00002551', - "boxVH;": '\U0000256C', - "boxVL;": '\U00002563', - "boxVR;": '\U00002560', - "boxVh;": '\U0000256B', - "boxVl;": '\U00002562', - "boxVr;": '\U0000255F', - "boxbox;": '\U000029C9', - "boxdL;": '\U00002555', - "boxdR;": '\U00002552', - "boxdl;": '\U00002510', - "boxdr;": '\U0000250C', - "boxh;": '\U00002500', - "boxhD;": '\U00002565', - "boxhU;": '\U00002568', - "boxhd;": '\U0000252C', - "boxhu;": '\U00002534', - "boxminus;": '\U0000229F', - "boxplus;": '\U0000229E', - "boxtimes;": '\U000022A0', - "boxuL;": '\U0000255B', - "boxuR;": '\U00002558', - "boxul;": '\U00002518', - "boxur;": '\U00002514', - "boxv;": '\U00002502', - "boxvH;": '\U0000256A', - "boxvL;": '\U00002561', - "boxvR;": '\U0000255E', - "boxvh;": '\U0000253C', - "boxvl;": '\U00002524', - "boxvr;": '\U0000251C', - "bprime;": '\U00002035', - "breve;": '\U000002D8', - "brvbar;": '\U000000A6', - "bscr;": '\U0001D4B7', - "bsemi;": '\U0000204F', - "bsim;": '\U0000223D', - "bsime;": '\U000022CD', - "bsol;": '\U0000005C', - "bsolb;": '\U000029C5', - "bsolhsub;": '\U000027C8', - "bull;": '\U00002022', - "bullet;": '\U00002022', - "bump;": '\U0000224E', - "bumpE;": '\U00002AAE', - "bumpe;": '\U0000224F', - "bumpeq;": '\U0000224F', - "cacute;": '\U00000107', - "cap;": '\U00002229', - "capand;": '\U00002A44', - "capbrcup;": '\U00002A49', - "capcap;": '\U00002A4B', - "capcup;": '\U00002A47', - "capdot;": '\U00002A40', - "caret;": '\U00002041', - "caron;": '\U000002C7', - "ccaps;": '\U00002A4D', - "ccaron;": '\U0000010D', - "ccedil;": '\U000000E7', - "ccirc;": '\U00000109', - "ccups;": '\U00002A4C', - "ccupssm;": '\U00002A50', - "cdot;": '\U0000010B', - "cedil;": '\U000000B8', - "cemptyv;": '\U000029B2', - "cent;": '\U000000A2', - "centerdot;": '\U000000B7', - "cfr;": '\U0001D520', - "chcy;": '\U00000447', - "check;": '\U00002713', - "checkmark;": '\U00002713', - "chi;": '\U000003C7', - "cir;": '\U000025CB', - "cirE;": '\U000029C3', - "circ;": '\U000002C6', - "circeq;": '\U00002257', - "circlearrowleft;": '\U000021BA', - "circlearrowright;": '\U000021BB', - "circledR;": '\U000000AE', - "circledS;": '\U000024C8', - "circledast;": '\U0000229B', - "circledcirc;": '\U0000229A', - "circleddash;": '\U0000229D', - "cire;": '\U00002257', - "cirfnint;": '\U00002A10', - "cirmid;": '\U00002AEF', - "cirscir;": '\U000029C2', - "clubs;": '\U00002663', - "clubsuit;": '\U00002663', - "colon;": '\U0000003A', - "colone;": '\U00002254', - "coloneq;": '\U00002254', - "comma;": '\U0000002C', - "commat;": '\U00000040', - "comp;": '\U00002201', - "compfn;": '\U00002218', - "complement;": '\U00002201', - "complexes;": '\U00002102', - "cong;": '\U00002245', - "congdot;": '\U00002A6D', - "conint;": '\U0000222E', - "copf;": '\U0001D554', - "coprod;": '\U00002210', - "copy;": '\U000000A9', - "copysr;": '\U00002117', - "crarr;": '\U000021B5', - "cross;": '\U00002717', - "cscr;": '\U0001D4B8', - "csub;": '\U00002ACF', - "csube;": '\U00002AD1', - "csup;": '\U00002AD0', - "csupe;": '\U00002AD2', - "ctdot;": '\U000022EF', - "cudarrl;": '\U00002938', - "cudarrr;": '\U00002935', - "cuepr;": '\U000022DE', - "cuesc;": '\U000022DF', - "cularr;": '\U000021B6', - "cularrp;": '\U0000293D', - "cup;": '\U0000222A', - "cupbrcap;": '\U00002A48', - "cupcap;": '\U00002A46', - "cupcup;": '\U00002A4A', - "cupdot;": '\U0000228D', - "cupor;": '\U00002A45', - "curarr;": '\U000021B7', - "curarrm;": '\U0000293C', - "curlyeqprec;": '\U000022DE', - "curlyeqsucc;": '\U000022DF', - "curlyvee;": '\U000022CE', - "curlywedge;": '\U000022CF', - "curren;": '\U000000A4', - "curvearrowleft;": '\U000021B6', - "curvearrowright;": '\U000021B7', - "cuvee;": '\U000022CE', - "cuwed;": '\U000022CF', - "cwconint;": '\U00002232', - "cwint;": '\U00002231', - "cylcty;": '\U0000232D', - "dArr;": '\U000021D3', - "dHar;": '\U00002965', - "dagger;": '\U00002020', - "daleth;": '\U00002138', - "darr;": '\U00002193', - "dash;": '\U00002010', - "dashv;": '\U000022A3', - "dbkarow;": '\U0000290F', - "dblac;": '\U000002DD', - "dcaron;": '\U0000010F', - "dcy;": '\U00000434', - "dd;": '\U00002146', - "ddagger;": '\U00002021', - "ddarr;": '\U000021CA', - "ddotseq;": '\U00002A77', - "deg;": '\U000000B0', - "delta;": '\U000003B4', - "demptyv;": '\U000029B1', - "dfisht;": '\U0000297F', - "dfr;": '\U0001D521', - "dharl;": '\U000021C3', - "dharr;": '\U000021C2', - "diam;": '\U000022C4', - "diamond;": '\U000022C4', - "diamondsuit;": '\U00002666', - "diams;": '\U00002666', - "die;": '\U000000A8', - "digamma;": '\U000003DD', - "disin;": '\U000022F2', - "div;": '\U000000F7', - "divide;": '\U000000F7', - "divideontimes;": '\U000022C7', - "divonx;": '\U000022C7', - "djcy;": '\U00000452', - "dlcorn;": '\U0000231E', - "dlcrop;": '\U0000230D', - "dollar;": '\U00000024', - "dopf;": '\U0001D555', - "dot;": '\U000002D9', - "doteq;": '\U00002250', - "doteqdot;": '\U00002251', - "dotminus;": '\U00002238', - "dotplus;": '\U00002214', - "dotsquare;": '\U000022A1', - "doublebarwedge;": '\U00002306', - "downarrow;": '\U00002193', - "downdownarrows;": '\U000021CA', - "downharpoonleft;": '\U000021C3', - "downharpoonright;": '\U000021C2', - "drbkarow;": '\U00002910', - "drcorn;": '\U0000231F', - "drcrop;": '\U0000230C', - "dscr;": '\U0001D4B9', - "dscy;": '\U00000455', - "dsol;": '\U000029F6', - "dstrok;": '\U00000111', - "dtdot;": '\U000022F1', - "dtri;": '\U000025BF', - "dtrif;": '\U000025BE', - "duarr;": '\U000021F5', - "duhar;": '\U0000296F', - "dwangle;": '\U000029A6', - "dzcy;": '\U0000045F', - "dzigrarr;": '\U000027FF', - "eDDot;": '\U00002A77', - "eDot;": '\U00002251', - "eacute;": '\U000000E9', - "easter;": '\U00002A6E', - "ecaron;": '\U0000011B', - "ecir;": '\U00002256', - "ecirc;": '\U000000EA', - "ecolon;": '\U00002255', - "ecy;": '\U0000044D', - "edot;": '\U00000117', - "ee;": '\U00002147', - "efDot;": '\U00002252', - "efr;": '\U0001D522', - "eg;": '\U00002A9A', - "egrave;": '\U000000E8', - "egs;": '\U00002A96', - "egsdot;": '\U00002A98', - "el;": '\U00002A99', - "elinters;": '\U000023E7', - "ell;": '\U00002113', - "els;": '\U00002A95', - "elsdot;": '\U00002A97', - "emacr;": '\U00000113', - "empty;": '\U00002205', - "emptyset;": '\U00002205', - "emptyv;": '\U00002205', - "emsp;": '\U00002003', - "emsp13;": '\U00002004', - "emsp14;": '\U00002005', - "eng;": '\U0000014B', - "ensp;": '\U00002002', - "eogon;": '\U00000119', - "eopf;": '\U0001D556', - "epar;": '\U000022D5', - "eparsl;": '\U000029E3', - "eplus;": '\U00002A71', - "epsi;": '\U000003B5', - "epsilon;": '\U000003B5', - "epsiv;": '\U000003F5', - "eqcirc;": '\U00002256', - "eqcolon;": '\U00002255', - "eqsim;": '\U00002242', - "eqslantgtr;": '\U00002A96', - "eqslantless;": '\U00002A95', - "equals;": '\U0000003D', - "equest;": '\U0000225F', - "equiv;": '\U00002261', - "equivDD;": '\U00002A78', - "eqvparsl;": '\U000029E5', - "erDot;": '\U00002253', - "erarr;": '\U00002971', - "escr;": '\U0000212F', - "esdot;": '\U00002250', - "esim;": '\U00002242', - "eta;": '\U000003B7', - "eth;": '\U000000F0', - "euml;": '\U000000EB', - "euro;": '\U000020AC', - "excl;": '\U00000021', - "exist;": '\U00002203', - "expectation;": '\U00002130', - "exponentiale;": '\U00002147', - "fallingdotseq;": '\U00002252', - "fcy;": '\U00000444', - "female;": '\U00002640', - "ffilig;": '\U0000FB03', - "fflig;": '\U0000FB00', - "ffllig;": '\U0000FB04', - "ffr;": '\U0001D523', - "filig;": '\U0000FB01', - "flat;": '\U0000266D', - "fllig;": '\U0000FB02', - "fltns;": '\U000025B1', - "fnof;": '\U00000192', - "fopf;": '\U0001D557', - "forall;": '\U00002200', - "fork;": '\U000022D4', - "forkv;": '\U00002AD9', - "fpartint;": '\U00002A0D', - "frac12;": '\U000000BD', - "frac13;": '\U00002153', - "frac14;": '\U000000BC', - "frac15;": '\U00002155', - "frac16;": '\U00002159', - "frac18;": '\U0000215B', - "frac23;": '\U00002154', - "frac25;": '\U00002156', - "frac34;": '\U000000BE', - "frac35;": '\U00002157', - "frac38;": '\U0000215C', - "frac45;": '\U00002158', - "frac56;": '\U0000215A', - "frac58;": '\U0000215D', - "frac78;": '\U0000215E', - "frasl;": '\U00002044', - "frown;": '\U00002322', - "fscr;": '\U0001D4BB', - "gE;": '\U00002267', - "gEl;": '\U00002A8C', - "gacute;": '\U000001F5', - "gamma;": '\U000003B3', - "gammad;": '\U000003DD', - "gap;": '\U00002A86', - "gbreve;": '\U0000011F', - "gcirc;": '\U0000011D', - "gcy;": '\U00000433', - "gdot;": '\U00000121', - "ge;": '\U00002265', - "gel;": '\U000022DB', - "geq;": '\U00002265', - "geqq;": '\U00002267', - "geqslant;": '\U00002A7E', - "ges;": '\U00002A7E', - "gescc;": '\U00002AA9', - "gesdot;": '\U00002A80', - "gesdoto;": '\U00002A82', - "gesdotol;": '\U00002A84', - "gesles;": '\U00002A94', - "gfr;": '\U0001D524', - "gg;": '\U0000226B', - "ggg;": '\U000022D9', - "gimel;": '\U00002137', - "gjcy;": '\U00000453', - "gl;": '\U00002277', - "glE;": '\U00002A92', - "gla;": '\U00002AA5', - "glj;": '\U00002AA4', - "gnE;": '\U00002269', - "gnap;": '\U00002A8A', - "gnapprox;": '\U00002A8A', - "gne;": '\U00002A88', - "gneq;": '\U00002A88', - "gneqq;": '\U00002269', - "gnsim;": '\U000022E7', - "gopf;": '\U0001D558', - "grave;": '\U00000060', - "gscr;": '\U0000210A', - "gsim;": '\U00002273', - "gsime;": '\U00002A8E', - "gsiml;": '\U00002A90', - "gt;": '\U0000003E', - "gtcc;": '\U00002AA7', - "gtcir;": '\U00002A7A', - "gtdot;": '\U000022D7', - "gtlPar;": '\U00002995', - "gtquest;": '\U00002A7C', - "gtrapprox;": '\U00002A86', - "gtrarr;": '\U00002978', - "gtrdot;": '\U000022D7', - "gtreqless;": '\U000022DB', - "gtreqqless;": '\U00002A8C', - "gtrless;": '\U00002277', - "gtrsim;": '\U00002273', - "hArr;": '\U000021D4', - "hairsp;": '\U0000200A', - "half;": '\U000000BD', - "hamilt;": '\U0000210B', - "hardcy;": '\U0000044A', - "harr;": '\U00002194', - "harrcir;": '\U00002948', - "harrw;": '\U000021AD', - "hbar;": '\U0000210F', - "hcirc;": '\U00000125', - "hearts;": '\U00002665', - "heartsuit;": '\U00002665', - "hellip;": '\U00002026', - "hercon;": '\U000022B9', - "hfr;": '\U0001D525', - "hksearow;": '\U00002925', - "hkswarow;": '\U00002926', - "hoarr;": '\U000021FF', - "homtht;": '\U0000223B', - "hookleftarrow;": '\U000021A9', - "hookrightarrow;": '\U000021AA', - "hopf;": '\U0001D559', - "horbar;": '\U00002015', - "hscr;": '\U0001D4BD', - "hslash;": '\U0000210F', - "hstrok;": '\U00000127', - "hybull;": '\U00002043', - "hyphen;": '\U00002010', - "iacute;": '\U000000ED', - "ic;": '\U00002063', - "icirc;": '\U000000EE', - "icy;": '\U00000438', - "iecy;": '\U00000435', - "iexcl;": '\U000000A1', - "iff;": '\U000021D4', - "ifr;": '\U0001D526', - "igrave;": '\U000000EC', - "ii;": '\U00002148', - "iiiint;": '\U00002A0C', - "iiint;": '\U0000222D', - "iinfin;": '\U000029DC', - "iiota;": '\U00002129', - "ijlig;": '\U00000133', - "imacr;": '\U0000012B', - "image;": '\U00002111', - "imagline;": '\U00002110', - "imagpart;": '\U00002111', - "imath;": '\U00000131', - "imof;": '\U000022B7', - "imped;": '\U000001B5', - "in;": '\U00002208', - "incare;": '\U00002105', - "infin;": '\U0000221E', - "infintie;": '\U000029DD', - "inodot;": '\U00000131', - "int;": '\U0000222B', - "intcal;": '\U000022BA', - "integers;": '\U00002124', - "intercal;": '\U000022BA', - "intlarhk;": '\U00002A17', - "intprod;": '\U00002A3C', - "iocy;": '\U00000451', - "iogon;": '\U0000012F', - "iopf;": '\U0001D55A', - "iota;": '\U000003B9', - "iprod;": '\U00002A3C', - "iquest;": '\U000000BF', - "iscr;": '\U0001D4BE', - "isin;": '\U00002208', - "isinE;": '\U000022F9', - "isindot;": '\U000022F5', - "isins;": '\U000022F4', - "isinsv;": '\U000022F3', - "isinv;": '\U00002208', - "it;": '\U00002062', - "itilde;": '\U00000129', - "iukcy;": '\U00000456', - "iuml;": '\U000000EF', - "jcirc;": '\U00000135', - "jcy;": '\U00000439', - "jfr;": '\U0001D527', - "jmath;": '\U00000237', - "jopf;": '\U0001D55B', - "jscr;": '\U0001D4BF', - "jsercy;": '\U00000458', - "jukcy;": '\U00000454', - "kappa;": '\U000003BA', - "kappav;": '\U000003F0', - "kcedil;": '\U00000137', - "kcy;": '\U0000043A', - "kfr;": '\U0001D528', - "kgreen;": '\U00000138', - "khcy;": '\U00000445', - "kjcy;": '\U0000045C', - "kopf;": '\U0001D55C', - "kscr;": '\U0001D4C0', - "lAarr;": '\U000021DA', - "lArr;": '\U000021D0', - "lAtail;": '\U0000291B', - "lBarr;": '\U0000290E', - "lE;": '\U00002266', - "lEg;": '\U00002A8B', - "lHar;": '\U00002962', - "lacute;": '\U0000013A', - "laemptyv;": '\U000029B4', - "lagran;": '\U00002112', - "lambda;": '\U000003BB', - "lang;": '\U000027E8', - "langd;": '\U00002991', - "langle;": '\U000027E8', - "lap;": '\U00002A85', - "laquo;": '\U000000AB', - "larr;": '\U00002190', - "larrb;": '\U000021E4', - "larrbfs;": '\U0000291F', - "larrfs;": '\U0000291D', - "larrhk;": '\U000021A9', - "larrlp;": '\U000021AB', - "larrpl;": '\U00002939', - "larrsim;": '\U00002973', - "larrtl;": '\U000021A2', - "lat;": '\U00002AAB', - "latail;": '\U00002919', - "late;": '\U00002AAD', - "lbarr;": '\U0000290C', - "lbbrk;": '\U00002772', - "lbrace;": '\U0000007B', - "lbrack;": '\U0000005B', - "lbrke;": '\U0000298B', - "lbrksld;": '\U0000298F', - "lbrkslu;": '\U0000298D', - "lcaron;": '\U0000013E', - "lcedil;": '\U0000013C', - "lceil;": '\U00002308', - "lcub;": '\U0000007B', - "lcy;": '\U0000043B', - "ldca;": '\U00002936', - "ldquo;": '\U0000201C', - "ldquor;": '\U0000201E', - "ldrdhar;": '\U00002967', - "ldrushar;": '\U0000294B', - "ldsh;": '\U000021B2', - "le;": '\U00002264', - "leftarrow;": '\U00002190', - "leftarrowtail;": '\U000021A2', - "leftharpoondown;": '\U000021BD', - "leftharpoonup;": '\U000021BC', - "leftleftarrows;": '\U000021C7', - "leftrightarrow;": '\U00002194', - "leftrightarrows;": '\U000021C6', - "leftrightharpoons;": '\U000021CB', - "leftrightsquigarrow;": '\U000021AD', - "leftthreetimes;": '\U000022CB', - "leg;": '\U000022DA', - "leq;": '\U00002264', - "leqq;": '\U00002266', - "leqslant;": '\U00002A7D', - "les;": '\U00002A7D', - "lescc;": '\U00002AA8', - "lesdot;": '\U00002A7F', - "lesdoto;": '\U00002A81', - "lesdotor;": '\U00002A83', - "lesges;": '\U00002A93', - "lessapprox;": '\U00002A85', - "lessdot;": '\U000022D6', - "lesseqgtr;": '\U000022DA', - "lesseqqgtr;": '\U00002A8B', - "lessgtr;": '\U00002276', - "lesssim;": '\U00002272', - "lfisht;": '\U0000297C', - "lfloor;": '\U0000230A', - "lfr;": '\U0001D529', - "lg;": '\U00002276', - "lgE;": '\U00002A91', - "lhard;": '\U000021BD', - "lharu;": '\U000021BC', - "lharul;": '\U0000296A', - "lhblk;": '\U00002584', - "ljcy;": '\U00000459', - "ll;": '\U0000226A', - "llarr;": '\U000021C7', - "llcorner;": '\U0000231E', - "llhard;": '\U0000296B', - "lltri;": '\U000025FA', - "lmidot;": '\U00000140', - "lmoust;": '\U000023B0', - "lmoustache;": '\U000023B0', - "lnE;": '\U00002268', - "lnap;": '\U00002A89', - "lnapprox;": '\U00002A89', - "lne;": '\U00002A87', - "lneq;": '\U00002A87', - "lneqq;": '\U00002268', - "lnsim;": '\U000022E6', - "loang;": '\U000027EC', - "loarr;": '\U000021FD', - "lobrk;": '\U000027E6', - "longleftarrow;": '\U000027F5', - "longleftrightarrow;": '\U000027F7', - "longmapsto;": '\U000027FC', - "longrightarrow;": '\U000027F6', - "looparrowleft;": '\U000021AB', - "looparrowright;": '\U000021AC', - "lopar;": '\U00002985', - "lopf;": '\U0001D55D', - "loplus;": '\U00002A2D', - "lotimes;": '\U00002A34', - "lowast;": '\U00002217', - "lowbar;": '\U0000005F', - "loz;": '\U000025CA', - "lozenge;": '\U000025CA', - "lozf;": '\U000029EB', - "lpar;": '\U00000028', - "lparlt;": '\U00002993', - "lrarr;": '\U000021C6', - "lrcorner;": '\U0000231F', - "lrhar;": '\U000021CB', - "lrhard;": '\U0000296D', - "lrm;": '\U0000200E', - "lrtri;": '\U000022BF', - "lsaquo;": '\U00002039', - "lscr;": '\U0001D4C1', - "lsh;": '\U000021B0', - "lsim;": '\U00002272', - "lsime;": '\U00002A8D', - "lsimg;": '\U00002A8F', - "lsqb;": '\U0000005B', - "lsquo;": '\U00002018', - "lsquor;": '\U0000201A', - "lstrok;": '\U00000142', - "lt;": '\U0000003C', - "ltcc;": '\U00002AA6', - "ltcir;": '\U00002A79', - "ltdot;": '\U000022D6', - "lthree;": '\U000022CB', - "ltimes;": '\U000022C9', - "ltlarr;": '\U00002976', - "ltquest;": '\U00002A7B', - "ltrPar;": '\U00002996', - "ltri;": '\U000025C3', - "ltrie;": '\U000022B4', - "ltrif;": '\U000025C2', - "lurdshar;": '\U0000294A', - "luruhar;": '\U00002966', - "mDDot;": '\U0000223A', - "macr;": '\U000000AF', - "male;": '\U00002642', - "malt;": '\U00002720', - "maltese;": '\U00002720', - "map;": '\U000021A6', - "mapsto;": '\U000021A6', - "mapstodown;": '\U000021A7', - "mapstoleft;": '\U000021A4', - "mapstoup;": '\U000021A5', - "marker;": '\U000025AE', - "mcomma;": '\U00002A29', - "mcy;": '\U0000043C', - "mdash;": '\U00002014', - "measuredangle;": '\U00002221', - "mfr;": '\U0001D52A', - "mho;": '\U00002127', - "micro;": '\U000000B5', - "mid;": '\U00002223', - "midast;": '\U0000002A', - "midcir;": '\U00002AF0', - "middot;": '\U000000B7', - "minus;": '\U00002212', - "minusb;": '\U0000229F', - "minusd;": '\U00002238', - "minusdu;": '\U00002A2A', - "mlcp;": '\U00002ADB', - "mldr;": '\U00002026', - "mnplus;": '\U00002213', - "models;": '\U000022A7', - "mopf;": '\U0001D55E', - "mp;": '\U00002213', - "mscr;": '\U0001D4C2', - "mstpos;": '\U0000223E', - "mu;": '\U000003BC', - "multimap;": '\U000022B8', - "mumap;": '\U000022B8', - "nLeftarrow;": '\U000021CD', - "nLeftrightarrow;": '\U000021CE', - "nRightarrow;": '\U000021CF', - "nVDash;": '\U000022AF', - "nVdash;": '\U000022AE', - "nabla;": '\U00002207', - "nacute;": '\U00000144', - "nap;": '\U00002249', - "napos;": '\U00000149', - "napprox;": '\U00002249', - "natur;": '\U0000266E', - "natural;": '\U0000266E', - "naturals;": '\U00002115', - "nbsp;": '\U000000A0', - "ncap;": '\U00002A43', - "ncaron;": '\U00000148', - "ncedil;": '\U00000146', - "ncong;": '\U00002247', - "ncup;": '\U00002A42', - "ncy;": '\U0000043D', - "ndash;": '\U00002013', - "ne;": '\U00002260', - "neArr;": '\U000021D7', - "nearhk;": '\U00002924', - "nearr;": '\U00002197', - "nearrow;": '\U00002197', - "nequiv;": '\U00002262', - "nesear;": '\U00002928', - "nexist;": '\U00002204', - "nexists;": '\U00002204', - "nfr;": '\U0001D52B', - "nge;": '\U00002271', - "ngeq;": '\U00002271', - "ngsim;": '\U00002275', - "ngt;": '\U0000226F', - "ngtr;": '\U0000226F', - "nhArr;": '\U000021CE', - "nharr;": '\U000021AE', - "nhpar;": '\U00002AF2', - "ni;": '\U0000220B', - "nis;": '\U000022FC', - "nisd;": '\U000022FA', - "niv;": '\U0000220B', - "njcy;": '\U0000045A', - "nlArr;": '\U000021CD', - "nlarr;": '\U0000219A', - "nldr;": '\U00002025', - "nle;": '\U00002270', - "nleftarrow;": '\U0000219A', - "nleftrightarrow;": '\U000021AE', - "nleq;": '\U00002270', - "nless;": '\U0000226E', - "nlsim;": '\U00002274', - "nlt;": '\U0000226E', - "nltri;": '\U000022EA', - "nltrie;": '\U000022EC', - "nmid;": '\U00002224', - "nopf;": '\U0001D55F', - "not;": '\U000000AC', - "notin;": '\U00002209', - "notinva;": '\U00002209', - "notinvb;": '\U000022F7', - "notinvc;": '\U000022F6', - "notni;": '\U0000220C', - "notniva;": '\U0000220C', - "notnivb;": '\U000022FE', - "notnivc;": '\U000022FD', - "npar;": '\U00002226', - "nparallel;": '\U00002226', - "npolint;": '\U00002A14', - "npr;": '\U00002280', - "nprcue;": '\U000022E0', - "nprec;": '\U00002280', - "nrArr;": '\U000021CF', - "nrarr;": '\U0000219B', - "nrightarrow;": '\U0000219B', - "nrtri;": '\U000022EB', - "nrtrie;": '\U000022ED', - "nsc;": '\U00002281', - "nsccue;": '\U000022E1', - "nscr;": '\U0001D4C3', - "nshortmid;": '\U00002224', - "nshortparallel;": '\U00002226', - "nsim;": '\U00002241', - "nsime;": '\U00002244', - "nsimeq;": '\U00002244', - "nsmid;": '\U00002224', - "nspar;": '\U00002226', - "nsqsube;": '\U000022E2', - "nsqsupe;": '\U000022E3', - "nsub;": '\U00002284', - "nsube;": '\U00002288', - "nsubseteq;": '\U00002288', - "nsucc;": '\U00002281', - "nsup;": '\U00002285', - "nsupe;": '\U00002289', - "nsupseteq;": '\U00002289', - "ntgl;": '\U00002279', - "ntilde;": '\U000000F1', - "ntlg;": '\U00002278', - "ntriangleleft;": '\U000022EA', - "ntrianglelefteq;": '\U000022EC', - "ntriangleright;": '\U000022EB', - "ntrianglerighteq;": '\U000022ED', - "nu;": '\U000003BD', - "num;": '\U00000023', - "numero;": '\U00002116', - "numsp;": '\U00002007', - "nvDash;": '\U000022AD', - "nvHarr;": '\U00002904', - "nvdash;": '\U000022AC', - "nvinfin;": '\U000029DE', - "nvlArr;": '\U00002902', - "nvrArr;": '\U00002903', - "nwArr;": '\U000021D6', - "nwarhk;": '\U00002923', - "nwarr;": '\U00002196', - "nwarrow;": '\U00002196', - "nwnear;": '\U00002927', - "oS;": '\U000024C8', - "oacute;": '\U000000F3', - "oast;": '\U0000229B', - "ocir;": '\U0000229A', - "ocirc;": '\U000000F4', - "ocy;": '\U0000043E', - "odash;": '\U0000229D', - "odblac;": '\U00000151', - "odiv;": '\U00002A38', - "odot;": '\U00002299', - "odsold;": '\U000029BC', - "oelig;": '\U00000153', - "ofcir;": '\U000029BF', - "ofr;": '\U0001D52C', - "ogon;": '\U000002DB', - "ograve;": '\U000000F2', - "ogt;": '\U000029C1', - "ohbar;": '\U000029B5', - "ohm;": '\U000003A9', - "oint;": '\U0000222E', - "olarr;": '\U000021BA', - "olcir;": '\U000029BE', - "olcross;": '\U000029BB', - "oline;": '\U0000203E', - "olt;": '\U000029C0', - "omacr;": '\U0000014D', - "omega;": '\U000003C9', - "omicron;": '\U000003BF', - "omid;": '\U000029B6', - "ominus;": '\U00002296', - "oopf;": '\U0001D560', - "opar;": '\U000029B7', - "operp;": '\U000029B9', - "oplus;": '\U00002295', - "or;": '\U00002228', - "orarr;": '\U000021BB', - "ord;": '\U00002A5D', - "order;": '\U00002134', - "orderof;": '\U00002134', - "ordf;": '\U000000AA', - "ordm;": '\U000000BA', - "origof;": '\U000022B6', - "oror;": '\U00002A56', - "orslope;": '\U00002A57', - "orv;": '\U00002A5B', - "oscr;": '\U00002134', - "oslash;": '\U000000F8', - "osol;": '\U00002298', - "otilde;": '\U000000F5', - "otimes;": '\U00002297', - "otimesas;": '\U00002A36', - "ouml;": '\U000000F6', - "ovbar;": '\U0000233D', - "par;": '\U00002225', - "para;": '\U000000B6', - "parallel;": '\U00002225', - "parsim;": '\U00002AF3', - "parsl;": '\U00002AFD', - "part;": '\U00002202', - "pcy;": '\U0000043F', - "percnt;": '\U00000025', - "period;": '\U0000002E', - "permil;": '\U00002030', - "perp;": '\U000022A5', - "pertenk;": '\U00002031', - "pfr;": '\U0001D52D', - "phi;": '\U000003C6', - "phiv;": '\U000003D5', - "phmmat;": '\U00002133', - "phone;": '\U0000260E', - "pi;": '\U000003C0', - "pitchfork;": '\U000022D4', - "piv;": '\U000003D6', - "planck;": '\U0000210F', - "planckh;": '\U0000210E', - "plankv;": '\U0000210F', - "plus;": '\U0000002B', - "plusacir;": '\U00002A23', - "plusb;": '\U0000229E', - "pluscir;": '\U00002A22', - "plusdo;": '\U00002214', - "plusdu;": '\U00002A25', - "pluse;": '\U00002A72', - "plusmn;": '\U000000B1', - "plussim;": '\U00002A26', - "plustwo;": '\U00002A27', - "pm;": '\U000000B1', - "pointint;": '\U00002A15', - "popf;": '\U0001D561', - "pound;": '\U000000A3', - "pr;": '\U0000227A', - "prE;": '\U00002AB3', - "prap;": '\U00002AB7', - "prcue;": '\U0000227C', - "pre;": '\U00002AAF', - "prec;": '\U0000227A', - "precapprox;": '\U00002AB7', - "preccurlyeq;": '\U0000227C', - "preceq;": '\U00002AAF', - "precnapprox;": '\U00002AB9', - "precneqq;": '\U00002AB5', - "precnsim;": '\U000022E8', - "precsim;": '\U0000227E', - "prime;": '\U00002032', - "primes;": '\U00002119', - "prnE;": '\U00002AB5', - "prnap;": '\U00002AB9', - "prnsim;": '\U000022E8', - "prod;": '\U0000220F', - "profalar;": '\U0000232E', - "profline;": '\U00002312', - "profsurf;": '\U00002313', - "prop;": '\U0000221D', - "propto;": '\U0000221D', - "prsim;": '\U0000227E', - "prurel;": '\U000022B0', - "pscr;": '\U0001D4C5', - "psi;": '\U000003C8', - "puncsp;": '\U00002008', - "qfr;": '\U0001D52E', - "qint;": '\U00002A0C', - "qopf;": '\U0001D562', - "qprime;": '\U00002057', - "qscr;": '\U0001D4C6', - "quaternions;": '\U0000210D', - "quatint;": '\U00002A16', - "quest;": '\U0000003F', - "questeq;": '\U0000225F', - "quot;": '\U00000022', - "rAarr;": '\U000021DB', - "rArr;": '\U000021D2', - "rAtail;": '\U0000291C', - "rBarr;": '\U0000290F', - "rHar;": '\U00002964', - "racute;": '\U00000155', - "radic;": '\U0000221A', - "raemptyv;": '\U000029B3', - "rang;": '\U000027E9', - "rangd;": '\U00002992', - "range;": '\U000029A5', - "rangle;": '\U000027E9', - "raquo;": '\U000000BB', - "rarr;": '\U00002192', - "rarrap;": '\U00002975', - "rarrb;": '\U000021E5', - "rarrbfs;": '\U00002920', - "rarrc;": '\U00002933', - "rarrfs;": '\U0000291E', - "rarrhk;": '\U000021AA', - "rarrlp;": '\U000021AC', - "rarrpl;": '\U00002945', - "rarrsim;": '\U00002974', - "rarrtl;": '\U000021A3', - "rarrw;": '\U0000219D', - "ratail;": '\U0000291A', - "ratio;": '\U00002236', - "rationals;": '\U0000211A', - "rbarr;": '\U0000290D', - "rbbrk;": '\U00002773', - "rbrace;": '\U0000007D', - "rbrack;": '\U0000005D', - "rbrke;": '\U0000298C', - "rbrksld;": '\U0000298E', - "rbrkslu;": '\U00002990', - "rcaron;": '\U00000159', - "rcedil;": '\U00000157', - "rceil;": '\U00002309', - "rcub;": '\U0000007D', - "rcy;": '\U00000440', - "rdca;": '\U00002937', - "rdldhar;": '\U00002969', - "rdquo;": '\U0000201D', - "rdquor;": '\U0000201D', - "rdsh;": '\U000021B3', - "real;": '\U0000211C', - "realine;": '\U0000211B', - "realpart;": '\U0000211C', - "reals;": '\U0000211D', - "rect;": '\U000025AD', - "reg;": '\U000000AE', - "rfisht;": '\U0000297D', - "rfloor;": '\U0000230B', - "rfr;": '\U0001D52F', - "rhard;": '\U000021C1', - "rharu;": '\U000021C0', - "rharul;": '\U0000296C', - "rho;": '\U000003C1', - "rhov;": '\U000003F1', - "rightarrow;": '\U00002192', - "rightarrowtail;": '\U000021A3', - "rightharpoondown;": '\U000021C1', - "rightharpoonup;": '\U000021C0', - "rightleftarrows;": '\U000021C4', - "rightleftharpoons;": '\U000021CC', - "rightrightarrows;": '\U000021C9', - "rightsquigarrow;": '\U0000219D', - "rightthreetimes;": '\U000022CC', - "ring;": '\U000002DA', - "risingdotseq;": '\U00002253', - "rlarr;": '\U000021C4', - "rlhar;": '\U000021CC', - "rlm;": '\U0000200F', - "rmoust;": '\U000023B1', - "rmoustache;": '\U000023B1', - "rnmid;": '\U00002AEE', - "roang;": '\U000027ED', - "roarr;": '\U000021FE', - "robrk;": '\U000027E7', - "ropar;": '\U00002986', - "ropf;": '\U0001D563', - "roplus;": '\U00002A2E', - "rotimes;": '\U00002A35', - "rpar;": '\U00000029', - "rpargt;": '\U00002994', - "rppolint;": '\U00002A12', - "rrarr;": '\U000021C9', - "rsaquo;": '\U0000203A', - "rscr;": '\U0001D4C7', - "rsh;": '\U000021B1', - "rsqb;": '\U0000005D', - "rsquo;": '\U00002019', - "rsquor;": '\U00002019', - "rthree;": '\U000022CC', - "rtimes;": '\U000022CA', - "rtri;": '\U000025B9', - "rtrie;": '\U000022B5', - "rtrif;": '\U000025B8', - "rtriltri;": '\U000029CE', - "ruluhar;": '\U00002968', - "rx;": '\U0000211E', - "sacute;": '\U0000015B', - "sbquo;": '\U0000201A', - "sc;": '\U0000227B', - "scE;": '\U00002AB4', - "scap;": '\U00002AB8', - "scaron;": '\U00000161', - "sccue;": '\U0000227D', - "sce;": '\U00002AB0', - "scedil;": '\U0000015F', - "scirc;": '\U0000015D', - "scnE;": '\U00002AB6', - "scnap;": '\U00002ABA', - "scnsim;": '\U000022E9', - "scpolint;": '\U00002A13', - "scsim;": '\U0000227F', - "scy;": '\U00000441', - "sdot;": '\U000022C5', - "sdotb;": '\U000022A1', - "sdote;": '\U00002A66', - "seArr;": '\U000021D8', - "searhk;": '\U00002925', - "searr;": '\U00002198', - "searrow;": '\U00002198', - "sect;": '\U000000A7', - "semi;": '\U0000003B', - "seswar;": '\U00002929', - "setminus;": '\U00002216', - "setmn;": '\U00002216', - "sext;": '\U00002736', - "sfr;": '\U0001D530', - "sfrown;": '\U00002322', - "sharp;": '\U0000266F', - "shchcy;": '\U00000449', - "shcy;": '\U00000448', - "shortmid;": '\U00002223', - "shortparallel;": '\U00002225', - "shy;": '\U000000AD', - "sigma;": '\U000003C3', - "sigmaf;": '\U000003C2', - "sigmav;": '\U000003C2', - "sim;": '\U0000223C', - "simdot;": '\U00002A6A', - "sime;": '\U00002243', - "simeq;": '\U00002243', - "simg;": '\U00002A9E', - "simgE;": '\U00002AA0', - "siml;": '\U00002A9D', - "simlE;": '\U00002A9F', - "simne;": '\U00002246', - "simplus;": '\U00002A24', - "simrarr;": '\U00002972', - "slarr;": '\U00002190', - "smallsetminus;": '\U00002216', - "smashp;": '\U00002A33', - "smeparsl;": '\U000029E4', - "smid;": '\U00002223', - "smile;": '\U00002323', - "smt;": '\U00002AAA', - "smte;": '\U00002AAC', - "softcy;": '\U0000044C', - "sol;": '\U0000002F', - "solb;": '\U000029C4', - "solbar;": '\U0000233F', - "sopf;": '\U0001D564', - "spades;": '\U00002660', - "spadesuit;": '\U00002660', - "spar;": '\U00002225', - "sqcap;": '\U00002293', - "sqcup;": '\U00002294', - "sqsub;": '\U0000228F', - "sqsube;": '\U00002291', - "sqsubset;": '\U0000228F', - "sqsubseteq;": '\U00002291', - "sqsup;": '\U00002290', - "sqsupe;": '\U00002292', - "sqsupset;": '\U00002290', - "sqsupseteq;": '\U00002292', - "squ;": '\U000025A1', - "square;": '\U000025A1', - "squarf;": '\U000025AA', - "squf;": '\U000025AA', - "srarr;": '\U00002192', - "sscr;": '\U0001D4C8', - "ssetmn;": '\U00002216', - "ssmile;": '\U00002323', - "sstarf;": '\U000022C6', - "star;": '\U00002606', - "starf;": '\U00002605', - "straightepsilon;": '\U000003F5', - "straightphi;": '\U000003D5', - "strns;": '\U000000AF', - "sub;": '\U00002282', - "subE;": '\U00002AC5', - "subdot;": '\U00002ABD', - "sube;": '\U00002286', - "subedot;": '\U00002AC3', - "submult;": '\U00002AC1', - "subnE;": '\U00002ACB', - "subne;": '\U0000228A', - "subplus;": '\U00002ABF', - "subrarr;": '\U00002979', - "subset;": '\U00002282', - "subseteq;": '\U00002286', - "subseteqq;": '\U00002AC5', - "subsetneq;": '\U0000228A', - "subsetneqq;": '\U00002ACB', - "subsim;": '\U00002AC7', - "subsub;": '\U00002AD5', - "subsup;": '\U00002AD3', - "succ;": '\U0000227B', - "succapprox;": '\U00002AB8', - "succcurlyeq;": '\U0000227D', - "succeq;": '\U00002AB0', - "succnapprox;": '\U00002ABA', - "succneqq;": '\U00002AB6', - "succnsim;": '\U000022E9', - "succsim;": '\U0000227F', - "sum;": '\U00002211', - "sung;": '\U0000266A', - "sup;": '\U00002283', - "sup1;": '\U000000B9', - "sup2;": '\U000000B2', - "sup3;": '\U000000B3', - "supE;": '\U00002AC6', - "supdot;": '\U00002ABE', - "supdsub;": '\U00002AD8', - "supe;": '\U00002287', - "supedot;": '\U00002AC4', - "suphsol;": '\U000027C9', - "suphsub;": '\U00002AD7', - "suplarr;": '\U0000297B', - "supmult;": '\U00002AC2', - "supnE;": '\U00002ACC', - "supne;": '\U0000228B', - "supplus;": '\U00002AC0', - "supset;": '\U00002283', - "supseteq;": '\U00002287', - "supseteqq;": '\U00002AC6', - "supsetneq;": '\U0000228B', - "supsetneqq;": '\U00002ACC', - "supsim;": '\U00002AC8', - "supsub;": '\U00002AD4', - "supsup;": '\U00002AD6', - "swArr;": '\U000021D9', - "swarhk;": '\U00002926', - "swarr;": '\U00002199', - "swarrow;": '\U00002199', - "swnwar;": '\U0000292A', - "szlig;": '\U000000DF', - "target;": '\U00002316', - "tau;": '\U000003C4', - "tbrk;": '\U000023B4', - "tcaron;": '\U00000165', - "tcedil;": '\U00000163', - "tcy;": '\U00000442', - "tdot;": '\U000020DB', - "telrec;": '\U00002315', - "tfr;": '\U0001D531', - "there4;": '\U00002234', - "therefore;": '\U00002234', - "theta;": '\U000003B8', - "thetasym;": '\U000003D1', - "thetav;": '\U000003D1', - "thickapprox;": '\U00002248', - "thicksim;": '\U0000223C', - "thinsp;": '\U00002009', - "thkap;": '\U00002248', - "thksim;": '\U0000223C', - "thorn;": '\U000000FE', - "tilde;": '\U000002DC', - "times;": '\U000000D7', - "timesb;": '\U000022A0', - "timesbar;": '\U00002A31', - "timesd;": '\U00002A30', - "tint;": '\U0000222D', - "toea;": '\U00002928', - "top;": '\U000022A4', - "topbot;": '\U00002336', - "topcir;": '\U00002AF1', - "topf;": '\U0001D565', - "topfork;": '\U00002ADA', - "tosa;": '\U00002929', - "tprime;": '\U00002034', - "trade;": '\U00002122', - "triangle;": '\U000025B5', - "triangledown;": '\U000025BF', - "triangleleft;": '\U000025C3', - "trianglelefteq;": '\U000022B4', - "triangleq;": '\U0000225C', - "triangleright;": '\U000025B9', - "trianglerighteq;": '\U000022B5', - "tridot;": '\U000025EC', - "trie;": '\U0000225C', - "triminus;": '\U00002A3A', - "triplus;": '\U00002A39', - "trisb;": '\U000029CD', - "tritime;": '\U00002A3B', - "trpezium;": '\U000023E2', - "tscr;": '\U0001D4C9', - "tscy;": '\U00000446', - "tshcy;": '\U0000045B', - "tstrok;": '\U00000167', - "twixt;": '\U0000226C', - "twoheadleftarrow;": '\U0000219E', - "twoheadrightarrow;": '\U000021A0', - "uArr;": '\U000021D1', - "uHar;": '\U00002963', - "uacute;": '\U000000FA', - "uarr;": '\U00002191', - "ubrcy;": '\U0000045E', - "ubreve;": '\U0000016D', - "ucirc;": '\U000000FB', - "ucy;": '\U00000443', - "udarr;": '\U000021C5', - "udblac;": '\U00000171', - "udhar;": '\U0000296E', - "ufisht;": '\U0000297E', - "ufr;": '\U0001D532', - "ugrave;": '\U000000F9', - "uharl;": '\U000021BF', - "uharr;": '\U000021BE', - "uhblk;": '\U00002580', - "ulcorn;": '\U0000231C', - "ulcorner;": '\U0000231C', - "ulcrop;": '\U0000230F', - "ultri;": '\U000025F8', - "umacr;": '\U0000016B', - "uml;": '\U000000A8', - "uogon;": '\U00000173', - "uopf;": '\U0001D566', - "uparrow;": '\U00002191', - "updownarrow;": '\U00002195', - "upharpoonleft;": '\U000021BF', - "upharpoonright;": '\U000021BE', - "uplus;": '\U0000228E', - "upsi;": '\U000003C5', - "upsih;": '\U000003D2', - "upsilon;": '\U000003C5', - "upuparrows;": '\U000021C8', - "urcorn;": '\U0000231D', - "urcorner;": '\U0000231D', - "urcrop;": '\U0000230E', - "uring;": '\U0000016F', - "urtri;": '\U000025F9', - "uscr;": '\U0001D4CA', - "utdot;": '\U000022F0', - "utilde;": '\U00000169', - "utri;": '\U000025B5', - "utrif;": '\U000025B4', - "uuarr;": '\U000021C8', - "uuml;": '\U000000FC', - "uwangle;": '\U000029A7', - "vArr;": '\U000021D5', - "vBar;": '\U00002AE8', - "vBarv;": '\U00002AE9', - "vDash;": '\U000022A8', - "vangrt;": '\U0000299C', - "varepsilon;": '\U000003F5', - "varkappa;": '\U000003F0', - "varnothing;": '\U00002205', - "varphi;": '\U000003D5', - "varpi;": '\U000003D6', - "varpropto;": '\U0000221D', - "varr;": '\U00002195', - "varrho;": '\U000003F1', - "varsigma;": '\U000003C2', - "vartheta;": '\U000003D1', - "vartriangleleft;": '\U000022B2', - "vartriangleright;": '\U000022B3', - "vcy;": '\U00000432', - "vdash;": '\U000022A2', - "vee;": '\U00002228', - "veebar;": '\U000022BB', - "veeeq;": '\U0000225A', - "vellip;": '\U000022EE', - "verbar;": '\U0000007C', - "vert;": '\U0000007C', - "vfr;": '\U0001D533', - "vltri;": '\U000022B2', - "vopf;": '\U0001D567', - "vprop;": '\U0000221D', - "vrtri;": '\U000022B3', - "vscr;": '\U0001D4CB', - "vzigzag;": '\U0000299A', - "wcirc;": '\U00000175', - "wedbar;": '\U00002A5F', - "wedge;": '\U00002227', - "wedgeq;": '\U00002259', - "weierp;": '\U00002118', - "wfr;": '\U0001D534', - "wopf;": '\U0001D568', - "wp;": '\U00002118', - "wr;": '\U00002240', - "wreath;": '\U00002240', - "wscr;": '\U0001D4CC', - "xcap;": '\U000022C2', - "xcirc;": '\U000025EF', - "xcup;": '\U000022C3', - "xdtri;": '\U000025BD', - "xfr;": '\U0001D535', - "xhArr;": '\U000027FA', - "xharr;": '\U000027F7', - "xi;": '\U000003BE', - "xlArr;": '\U000027F8', - "xlarr;": '\U000027F5', - "xmap;": '\U000027FC', - "xnis;": '\U000022FB', - "xodot;": '\U00002A00', - "xopf;": '\U0001D569', - "xoplus;": '\U00002A01', - "xotime;": '\U00002A02', - "xrArr;": '\U000027F9', - "xrarr;": '\U000027F6', - "xscr;": '\U0001D4CD', - "xsqcup;": '\U00002A06', - "xuplus;": '\U00002A04', - "xutri;": '\U000025B3', - "xvee;": '\U000022C1', - "xwedge;": '\U000022C0', - "yacute;": '\U000000FD', - "yacy;": '\U0000044F', - "ycirc;": '\U00000177', - "ycy;": '\U0000044B', - "yen;": '\U000000A5', - "yfr;": '\U0001D536', - "yicy;": '\U00000457', - "yopf;": '\U0001D56A', - "yscr;": '\U0001D4CE', - "yucy;": '\U0000044E', - "yuml;": '\U000000FF', - "zacute;": '\U0000017A', - "zcaron;": '\U0000017E', - "zcy;": '\U00000437', - "zdot;": '\U0000017C', - "zeetrf;": '\U00002128', - "zeta;": '\U000003B6', - "zfr;": '\U0001D537', - "zhcy;": '\U00000436', - "zigrarr;": '\U000021DD', - "zopf;": '\U0001D56B', - "zscr;": '\U0001D4CF', - "zwj;": '\U0000200D', - "zwnj;": '\U0000200C', - "AElig": '\U000000C6', - "AMP": '\U00000026', - "Aacute": '\U000000C1', - "Acirc": '\U000000C2', - "Agrave": '\U000000C0', - "Aring": '\U000000C5', - "Atilde": '\U000000C3', - "Auml": '\U000000C4', - "COPY": '\U000000A9', - "Ccedil": '\U000000C7', - "ETH": '\U000000D0', - "Eacute": '\U000000C9', - "Ecirc": '\U000000CA', - "Egrave": '\U000000C8', - "Euml": '\U000000CB', - "GT": '\U0000003E', - "Iacute": '\U000000CD', - "Icirc": '\U000000CE', - "Igrave": '\U000000CC', - "Iuml": '\U000000CF', - "LT": '\U0000003C', - "Ntilde": '\U000000D1', - "Oacute": '\U000000D3', - "Ocirc": '\U000000D4', - "Ograve": '\U000000D2', - "Oslash": '\U000000D8', - "Otilde": '\U000000D5', - "Ouml": '\U000000D6', - "QUOT": '\U00000022', - "REG": '\U000000AE', - "THORN": '\U000000DE', - "Uacute": '\U000000DA', - "Ucirc": '\U000000DB', - "Ugrave": '\U000000D9', - "Uuml": '\U000000DC', - "Yacute": '\U000000DD', - "aacute": '\U000000E1', - "acirc": '\U000000E2', - "acute": '\U000000B4', - "aelig": '\U000000E6', - "agrave": '\U000000E0', - "amp": '\U00000026', - "aring": '\U000000E5', - "atilde": '\U000000E3', - "auml": '\U000000E4', - "brvbar": '\U000000A6', - "ccedil": '\U000000E7', - "cedil": '\U000000B8', - "cent": '\U000000A2', - "copy": '\U000000A9', - "curren": '\U000000A4', - "deg": '\U000000B0', - "divide": '\U000000F7', - "eacute": '\U000000E9', - "ecirc": '\U000000EA', - "egrave": '\U000000E8', - "eth": '\U000000F0', - "euml": '\U000000EB', - "frac12": '\U000000BD', - "frac14": '\U000000BC', - "frac34": '\U000000BE', - "gt": '\U0000003E', - "iacute": '\U000000ED', - "icirc": '\U000000EE', - "iexcl": '\U000000A1', - "igrave": '\U000000EC', - "iquest": '\U000000BF', - "iuml": '\U000000EF', - "laquo": '\U000000AB', - "lt": '\U0000003C', - "macr": '\U000000AF', - "micro": '\U000000B5', - "middot": '\U000000B7', - "nbsp": '\U000000A0', - "not": '\U000000AC', - "ntilde": '\U000000F1', - "oacute": '\U000000F3', - "ocirc": '\U000000F4', - "ograve": '\U000000F2', - "ordf": '\U000000AA', - "ordm": '\U000000BA', - "oslash": '\U000000F8', - "otilde": '\U000000F5', - "ouml": '\U000000F6', - "para": '\U000000B6', - "plusmn": '\U000000B1', - "pound": '\U000000A3', - "quot": '\U00000022', - "raquo": '\U000000BB', - "reg": '\U000000AE', - "sect": '\U000000A7', - "shy": '\U000000AD', - "sup1": '\U000000B9', - "sup2": '\U000000B2', - "sup3": '\U000000B3', - "szlig": '\U000000DF', - "thorn": '\U000000FE', - "times": '\U000000D7', - "uacute": '\U000000FA', - "ucirc": '\U000000FB', - "ugrave": '\U000000F9', - "uml": '\U000000A8', - "uuml": '\U000000FC', - "yacute": '\U000000FD', - "yen": '\U000000A5', - "yuml": '\U000000FF', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', } // HTML entities that are two unicode codepoints. diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go index d3b3844..01477a9 100644 --- a/vendor/golang.org/x/net/html/foreign.go +++ b/vendor/golang.org/x/net/html/foreign.go @@ -67,7 +67,7 @@ func mathMLTextIntegrationPoint(n *Node) bool { return false } -// Section 12.2.5.5. +// Section 12.2.6.5. var breakout = map[string]bool{ "b": true, "big": true, @@ -115,7 +115,7 @@ var breakout = map[string]bool{ "var": true, } -// Section 12.2.5.5. +// Section 12.2.6.5. var svgTagNameAdjustments = map[string]string{ "altglyph": "altGlyph", "altglyphdef": "altGlyphDef", @@ -155,7 +155,7 @@ var svgTagNameAdjustments = map[string]string{ "textpath": "textPath", } -// Section 12.2.5.1 +// Section 12.2.6.1 var mathMLAttributeAdjustments = map[string]string{ "definitionurl": "definitionURL", } diff --git a/vendor/golang.org/x/net/html/node.go b/vendor/golang.org/x/net/html/node.go index 26b657a..2c1cade 100644 --- a/vendor/golang.org/x/net/html/node.go +++ b/vendor/golang.org/x/net/html/node.go @@ -21,9 +21,10 @@ const ( scopeMarkerNode ) -// Section 12.2.3.3 says "scope markers are inserted when entering applet -// elements, buttons, object elements, marquees, table cells, and table -// captions, and are used to prevent formatting from 'leaking'". +// Section 12.2.4.3 says "The markers are inserted when entering applet, +// object, marquee, template, td, th, and caption elements, and are used +// to prevent formatting from "leaking" into applet, object, marquee, +// template, td, th, and caption elements". var scopeMarker = Node{Type: scopeMarkerNode} // A Node consists of a NodeType and some Data (tag name for element nodes, @@ -173,6 +174,16 @@ func (s *nodeStack) index(n *Node) int { return -1 } +// contains returns whether a is within s. +func (s *nodeStack) contains(a atom.Atom) bool { + for _, n := range *s { + if n.DataAtom == a { + return true + } + } + return false +} + // insert inserts a node at the given index. func (s *nodeStack) insert(i int, n *Node) { (*s) = append(*s, nil) @@ -191,3 +202,19 @@ func (s *nodeStack) remove(n *Node) { (*s)[j] = nil *s = (*s)[:j] } + +type insertionModeStack []insertionMode + +func (s *insertionModeStack) pop() (im insertionMode) { + i := len(*s) + im = (*s)[i-1] + *s = (*s)[:i-1] + return im +} + +func (s *insertionModeStack) top() insertionMode { + if i := len(*s); i > 0 { + return (*s)[i-1] + } + return nil +} diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go index be4b2bf..7e539b1 100644 --- a/vendor/golang.org/x/net/html/parse.go +++ b/vendor/golang.org/x/net/html/parse.go @@ -25,20 +25,22 @@ type parser struct { hasSelfClosingToken bool // doc is the document root element. doc *Node - // The stack of open elements (section 12.2.3.2) and active formatting - // elements (section 12.2.3.3). + // The stack of open elements (section 12.2.4.2) and active formatting + // elements (section 12.2.4.3). oe, afe nodeStack - // Element pointers (section 12.2.3.4). + // Element pointers (section 12.2.4.4). head, form *Node - // Other parsing state flags (section 12.2.3.5). + // Other parsing state flags (section 12.2.4.5). scripting, framesetOK bool + // The stack of template insertion modes + templateStack insertionModeStack // im is the current insertion mode. im insertionMode // originalIM is the insertion mode to go back to after completing a text // or inTableText insertion mode. originalIM insertionMode // fosterParenting is whether new elements should be inserted according to - // the foster parenting rules (section 12.2.5.3). + // the foster parenting rules (section 12.2.6.1). fosterParenting bool // quirks is whether the parser is operating in "quirks mode." quirks bool @@ -56,7 +58,7 @@ func (p *parser) top() *Node { return p.doc } -// Stop tags for use in popUntil. These come from section 12.2.3.2. +// Stop tags for use in popUntil. These come from section 12.2.4.2. var ( defaultScopeStopTags = map[string][]a.Atom{ "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template}, @@ -79,7 +81,7 @@ const ( // popUntil pops the stack of open elements at the highest element whose tag // is in matchTags, provided there is no higher element in the scope's stop -// tags (as defined in section 12.2.3.2). It returns whether or not there was +// tags (as defined in section 12.2.4.2). It returns whether or not there was // such an element. If there was not, popUntil leaves the stack unchanged. // // For example, the set of stop tags for table scope is: "html", "table". If @@ -126,7 +128,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int { return -1 } case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { + if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template { return -1 } case selectScope: @@ -162,17 +164,17 @@ func (p *parser) clearStackToContext(s scope) { tagAtom := p.oe[i].DataAtom switch s { case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { + if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template { p.oe = p.oe[:i+1] return } case tableRowScope: - if tagAtom == a.Html || tagAtom == a.Tr { + if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template { p.oe = p.oe[:i+1] return } case tableBodyScope: - if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead { + if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template { p.oe = p.oe[:i+1] return } @@ -183,7 +185,7 @@ func (p *parser) clearStackToContext(s scope) { } // generateImpliedEndTags pops nodes off the stack of open elements as long as -// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt. +// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc. // If exceptions are specified, nodes with that name will not be popped off. func (p *parser) generateImpliedEndTags(exceptions ...string) { var i int @@ -192,7 +194,7 @@ loop: n := p.oe[i] if n.Type == ElementNode { switch n.DataAtom { - case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt: + case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc: for _, except := range exceptions { if n.Data == except { break loop @@ -207,6 +209,27 @@ loop: p.oe = p.oe[:i+1] } +// generateAllImpliedEndTags pops nodes off the stack of open elements as long as +// the top node has a tag name of caption, colgroup, dd, div, dt, li, optgroup, option, p, rb, +// rp, rt, rtc, span, tbody, td, tfoot, th, thead or tr. +func (p *parser) generateAllImpliedEndTags() { + var i int + for i = len(p.oe) - 1; i >= 0; i-- { + n := p.oe[i] + if n.Type == ElementNode { + switch n.DataAtom { + // TODO: remove this divergence from the HTML5 spec + case a.Caption, a.Colgroup, a.Dd, a.Div, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, + a.Rp, a.Rt, a.Rtc, a.Span, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: + continue + } + } + break + } + + p.oe = p.oe[:i+1] +} + // addChild adds a child node n to the top element, and pushes n onto the stack // of open elements if it is an element node. func (p *parser) addChild(n *Node) { @@ -234,9 +257,9 @@ func (p *parser) shouldFosterParent() bool { } // fosterParent adds a child node according to the foster parenting rules. -// Section 12.2.5.3, "foster parenting". +// Section 12.2.6.1, "foster parenting". func (p *parser) fosterParent(n *Node) { - var table, parent, prev *Node + var table, parent, prev, template *Node var i int for i = len(p.oe) - 1; i >= 0; i-- { if p.oe[i].DataAtom == a.Table { @@ -245,6 +268,19 @@ func (p *parser) fosterParent(n *Node) { } } + var j int + for j = len(p.oe) - 1; j >= 0; j-- { + if p.oe[j].DataAtom == a.Template { + template = p.oe[j] + break + } + } + + if template != nil && (table == nil || j < i) { + template.AppendChild(n) + return + } + if table == nil { // The foster parent is the html element. parent = p.oe[0] @@ -304,7 +340,7 @@ func (p *parser) addElement() { }) } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) addFormattingElement() { tagAtom, attr := p.tok.DataAtom, p.tok.Attr p.addElement() @@ -351,7 +387,7 @@ findIdenticalElements: p.afe = append(p.afe, p.top()) } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) clearActiveFormattingElements() { for { n := p.afe.pop() @@ -361,7 +397,7 @@ func (p *parser) clearActiveFormattingElements() { } } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) reconstructActiveFormattingElements() { n := p.afe.top() if n == nil { @@ -390,12 +426,12 @@ func (p *parser) reconstructActiveFormattingElements() { } } -// Section 12.2.4. +// Section 12.2.5. func (p *parser) acknowledgeSelfClosingTag() { p.hasSelfClosingToken = false } -// An insertion mode (section 12.2.3.1) is the state transition function from +// An insertion mode (section 12.2.4.1) is the state transition function from // a particular state in the HTML5 parser's state machine. It updates the // parser's fields depending on parser.tok (where ErrorToken means EOF). // It returns whether the token was consumed. @@ -403,7 +439,7 @@ type insertionMode func(*parser) bool // setOriginalIM sets the insertion mode to return to after completing a text or // inTableText insertion mode. -// Section 12.2.3.1, "using the rules for". +// Section 12.2.4.1, "using the rules for". func (p *parser) setOriginalIM() { if p.originalIM != nil { panic("html: bad parser state: originalIM was set twice") @@ -411,18 +447,38 @@ func (p *parser) setOriginalIM() { p.originalIM = p.im } -// Section 12.2.3.1, "reset the insertion mode". +// Section 12.2.4.1, "reset the insertion mode". func (p *parser) resetInsertionMode() { for i := len(p.oe) - 1; i >= 0; i-- { n := p.oe[i] - if i == 0 && p.context != nil { + last := i == 0 + if last && p.context != nil { n = p.context } switch n.DataAtom { case a.Select: + if !last { + for ancestor, first := n, p.oe[0]; ancestor != first; { + if ancestor == first { + break + } + ancestor = p.oe[p.oe.index(ancestor)-1] + switch ancestor.DataAtom { + case a.Template: + p.im = inSelectIM + return + case a.Table: + p.im = inSelectInTableIM + return + } + } + } p.im = inSelectIM case a.Td, a.Th: + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 p.im = inCellIM case a.Tr: p.im = inRowIM @@ -434,25 +490,37 @@ func (p *parser) resetInsertionMode() { p.im = inColumnGroupIM case a.Table: p.im = inTableIM + case a.Template: + p.im = p.templateStack.top() case a.Head: - p.im = inBodyIM + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 + p.im = inHeadIM case a.Body: p.im = inBodyIM case a.Frameset: p.im = inFramesetIM case a.Html: - p.im = beforeHeadIM + if p.head == nil { + p.im = beforeHeadIM + } else { + p.im = afterHeadIM + } default: + if last { + p.im = inBodyIM + return + } continue } return } - p.im = inBodyIM } const whitespace = " \t\r\n\f" -// Section 12.2.5.4.1. +// Section 12.2.6.4.1. func initialIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -479,7 +547,7 @@ func initialIM(p *parser) bool { return false } -// Section 12.2.5.4.2. +// Section 12.2.6.4.2. func beforeHTMLIM(p *parser) bool { switch p.tok.Type { case DoctypeToken: @@ -517,7 +585,7 @@ func beforeHTMLIM(p *parser) bool { return false } -// Section 12.2.5.4.3. +// Section 12.2.6.4.3. func beforeHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -560,7 +628,7 @@ func beforeHeadIM(p *parser) bool { return false } -// Section 12.2.5.4.4. +// Section 12.2.6.4.4. func inHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -590,19 +658,36 @@ func inHeadIM(p *parser) bool { case a.Head: // Ignore the token. return true + case a.Template: + p.addElement() + p.afe = append(p.afe, &scopeMarker) + p.framesetOK = false + p.im = inTemplateIM + p.templateStack = append(p.templateStack, inTemplateIM) + return true } case EndTagToken: switch p.tok.DataAtom { case a.Head: - n := p.oe.pop() - if n.DataAtom != a.Head { - panic("html: bad parser state: element not found, in the in-head insertion mode") - } + p.oe.pop() p.im = afterHeadIM return true case a.Body, a.Html, a.Br: p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) return false + case a.Template: + if !p.oe.contains(a.Template) { + return true + } + p.generateAllImpliedEndTags() + if n := p.oe.top(); n.DataAtom != a.Template { + return true + } + p.popUntil(defaultScope, a.Template) + p.clearActiveFormattingElements() + p.templateStack.pop() + p.resetInsertionMode() + return true default: // Ignore the token. return true @@ -622,7 +707,7 @@ func inHeadIM(p *parser) bool { return false } -// Section 12.2.5.4.6. +// Section 12.2.6.4.6. func afterHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -648,7 +733,7 @@ func afterHeadIM(p *parser) bool { p.addElement() p.im = inFramesetIM return true - case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: + case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: p.oe = append(p.oe, p.head) defer p.oe.remove(p.head) return inHeadIM(p) @@ -660,6 +745,8 @@ func afterHeadIM(p *parser) bool { switch p.tok.DataAtom { case a.Body, a.Html, a.Br: // Drop down to creating an implied tag. + case a.Template: + return inHeadIM(p) default: // Ignore the token. return true @@ -697,7 +784,7 @@ func copyAttributes(dst *Node, src Token) { } } -// Section 12.2.5.4.7. +// Section 12.2.6.4.7. func inBodyIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -727,10 +814,16 @@ func inBodyIM(p *parser) bool { case StartTagToken: switch p.tok.DataAtom { case a.Html: + if p.oe.contains(a.Template) { + return true + } copyAttributes(p.oe[0], p.tok) - case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: + case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: return inHeadIM(p) case a.Body: + if p.oe.contains(a.Template) { + return true + } if len(p.oe) >= 2 { body := p.oe[1] if body.Type == ElementNode && body.DataAtom == a.Body { @@ -767,9 +860,13 @@ func inBodyIM(p *parser) bool { // The newline, if any, will be dealt with by the TextToken case. p.framesetOK = false case a.Form: - if p.form == nil { - p.popUntil(buttonScope, a.P) - p.addElement() + if p.form != nil && !p.oe.contains(a.Template) { + // Ignore the token + return true + } + p.popUntil(buttonScope, a.P) + p.addElement() + if !p.oe.contains(a.Template) { p.form = p.top() } case a.Li: @@ -952,11 +1049,16 @@ func inBodyIM(p *parser) bool { } p.reconstructActiveFormattingElements() p.addElement() - case a.Rp, a.Rt: + case a.Rb, a.Rtc: if p.elementInScope(defaultScope, a.Ruby) { p.generateImpliedEndTags() } p.addElement() + case a.Rp, a.Rt: + if p.elementInScope(defaultScope, a.Ruby) { + p.generateImpliedEndTags("rtc") + } + p.addElement() case a.Math, a.Svg: p.reconstructActiveFormattingElements() if p.tok.DataAtom == a.Math { @@ -972,7 +1074,13 @@ func inBodyIM(p *parser) bool { p.acknowledgeSelfClosingTag() } return true - case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: + case a.Frame: + // TODO: remove this divergence from the HTML5 spec. + if p.oe.contains(a.Template) { + p.addElement() + return true + } + case a.Caption, a.Col, a.Colgroup, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: // Ignore the token. default: p.reconstructActiveFormattingElements() @@ -993,15 +1101,29 @@ func inBodyIM(p *parser) bool { case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul: p.popUntil(defaultScope, p.tok.DataAtom) case a.Form: - node := p.form - p.form = nil - i := p.indexOfElementInScope(defaultScope, a.Form) - if node == nil || i == -1 || p.oe[i] != node { - // Ignore the token. - return true + if p.oe.contains(a.Template) { + i := p.indexOfElementInScope(defaultScope, a.Form) + if i == -1 { + // Ignore the token. + return true + } + p.generateImpliedEndTags() + if p.oe[i].DataAtom != a.Form { + // Ignore the token. + return true + } + p.popUntil(defaultScope, a.Form) + } else { + node := p.form + p.form = nil + i := p.indexOfElementInScope(defaultScope, a.Form) + if node == nil || i == -1 || p.oe[i] != node { + // Ignore the token. + return true + } + p.generateImpliedEndTags() + p.oe.remove(node) } - p.generateImpliedEndTags() - p.oe.remove(node) case a.P: if !p.elementInScope(buttonScope, a.P) { p.parseImpliedToken(StartTagToken, a.P, a.P.String()) @@ -1022,6 +1144,8 @@ func inBodyIM(p *parser) bool { case a.Br: p.tok.Type = StartTagToken return false + case a.Template: + return inHeadIM(p) default: p.inBodyEndTagOther(p.tok.DataAtom) } @@ -1030,6 +1154,21 @@ func inBodyIM(p *parser) bool { Type: CommentNode, Data: p.tok.Data, }) + case ErrorToken: + // TODO: remove this divergence from the HTML5 spec. + if len(p.templateStack) > 0 { + p.im = inTemplateIM + return false + } else { + for _, e := range p.oe { + switch e.DataAtom { + case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th, + a.Thead, a.Tr, a.Body, a.Html: + default: + return true + } + } + } } return true @@ -1135,6 +1274,12 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { switch commonAncestor.DataAtom { case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr: p.fosterParent(lastNode) + case a.Template: + // TODO: remove namespace checking + if commonAncestor.Namespace == "html" { + commonAncestor = commonAncestor.LastChild + } + fallthrough default: commonAncestor.AppendChild(lastNode) } @@ -1160,7 +1305,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { } // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM. -// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content +// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign func (p *parser) inBodyEndTagOther(tagAtom a.Atom) { for i := len(p.oe) - 1; i >= 0; i-- { @@ -1174,7 +1319,7 @@ func (p *parser) inBodyEndTagOther(tagAtom a.Atom) { } } -// Section 12.2.5.4.8. +// Section 12.2.6.4.8. func textIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1203,7 +1348,7 @@ func textIM(p *parser) bool { return p.tok.Type == EndTagToken } -// Section 12.2.5.4.9. +// Section 12.2.6.4.9. func inTableIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1249,7 +1394,7 @@ func inTableIM(p *parser) bool { } // Ignore the token. return true - case a.Style, a.Script: + case a.Style, a.Script, a.Template: return inHeadIM(p) case a.Input: for _, t := range p.tok.Attr { @@ -1261,7 +1406,7 @@ func inTableIM(p *parser) bool { } // Otherwise drop down to the default action. case a.Form: - if p.form != nil { + if p.oe.contains(a.Template) || p.form != nil { // Ignore the token. return true } @@ -1291,6 +1436,8 @@ func inTableIM(p *parser) bool { case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: // Ignore the token. return true + case a.Template: + return inHeadIM(p) } case CommentToken: p.addChild(&Node{ @@ -1309,7 +1456,7 @@ func inTableIM(p *parser) bool { return inBodyIM(p) } -// Section 12.2.5.4.11. +// Section 12.2.6.4.11. func inCaptionIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1355,7 +1502,7 @@ func inCaptionIM(p *parser) bool { return inBodyIM(p) } -// Section 12.2.5.4.12. +// Section 12.2.6.4.12. func inColumnGroupIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -1386,11 +1533,13 @@ func inColumnGroupIM(p *parser) bool { p.oe.pop() p.acknowledgeSelfClosingTag() return true + case a.Template: + return inHeadIM(p) } case EndTagToken: switch p.tok.DataAtom { case a.Colgroup: - if p.oe.top().DataAtom != a.Html { + if p.oe.top().DataAtom == a.Colgroup { p.oe.pop() p.im = inTableIM } @@ -1398,17 +1547,19 @@ func inColumnGroupIM(p *parser) bool { case a.Col: // Ignore the token. return true + case a.Template: + return inHeadIM(p) } } - if p.oe.top().DataAtom != a.Html { - p.oe.pop() - p.im = inTableIM - return false + if p.oe.top().DataAtom != a.Colgroup { + return true } - return true + p.oe.pop() + p.im = inTableIM + return false } -// Section 12.2.5.4.13. +// Section 12.2.6.4.13. func inTableBodyIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1460,7 +1611,7 @@ func inTableBodyIM(p *parser) bool { return inTableIM(p) } -// Section 12.2.5.4.14. +// Section 12.2.6.4.14. func inRowIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1511,7 +1662,7 @@ func inRowIM(p *parser) bool { return inTableIM(p) } -// Section 12.2.5.4.15. +// Section 12.2.6.4.15. func inCellIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1560,7 +1711,7 @@ func inCellIM(p *parser) bool { return inBodyIM(p) } -// Section 12.2.5.4.16. +// Section 12.2.6.4.16. func inSelectIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1597,7 +1748,7 @@ func inSelectIM(p *parser) bool { p.tokenizer.NextIsNotRawText() // Ignore the token. return true - case a.Script: + case a.Script, a.Template: return inHeadIM(p) } case EndTagToken: @@ -1618,6 +1769,8 @@ func inSelectIM(p *parser) bool { if p.popUntil(selectScope, a.Select) { p.resetInsertionMode() } + case a.Template: + return inHeadIM(p) } case CommentToken: p.addChild(&Node{ @@ -1632,7 +1785,7 @@ func inSelectIM(p *parser) bool { return true } -// Section 12.2.5.4.17. +// Section 12.2.6.4.17. func inSelectInTableIM(p *parser) bool { switch p.tok.Type { case StartTagToken, EndTagToken: @@ -1650,7 +1803,62 @@ func inSelectInTableIM(p *parser) bool { return inSelectIM(p) } -// Section 12.2.5.4.18. +// Section 12.2.6.4.18. +func inTemplateIM(p *parser) bool { + switch p.tok.Type { + case TextToken, CommentToken, DoctypeToken: + return inBodyIM(p) + case StartTagToken: + switch p.tok.DataAtom { + case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: + return inHeadIM(p) + case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead: + p.templateStack.pop() + p.templateStack = append(p.templateStack, inTableIM) + p.im = inTableIM + return false + case a.Col: + p.templateStack.pop() + p.templateStack = append(p.templateStack, inColumnGroupIM) + p.im = inColumnGroupIM + return false + case a.Tr: + p.templateStack.pop() + p.templateStack = append(p.templateStack, inTableBodyIM) + p.im = inTableBodyIM + return false + case a.Td, a.Th: + p.templateStack.pop() + p.templateStack = append(p.templateStack, inRowIM) + p.im = inRowIM + return false + default: + p.templateStack.pop() + p.templateStack = append(p.templateStack, inBodyIM) + p.im = inBodyIM + return false + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Template: + return inHeadIM(p) + default: + // Ignore the token. + return true + } + } + if !p.oe.contains(a.Template) { + // Ignore the token. + return true + } + p.popUntil(defaultScope, a.Template) + p.clearActiveFormattingElements() + p.templateStack.pop() + p.resetInsertionMode() + return false +} + +// Section 12.2.6.4.19. func afterBodyIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1688,7 +1896,7 @@ func afterBodyIM(p *parser) bool { return false } -// Section 12.2.5.4.19. +// Section 12.2.6.4.20. func inFramesetIM(p *parser) bool { switch p.tok.Type { case CommentToken: @@ -1720,6 +1928,11 @@ func inFramesetIM(p *parser) bool { p.acknowledgeSelfClosingTag() case a.Noframes: return inHeadIM(p) + case a.Template: + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 + return inTemplateIM(p) } case EndTagToken: switch p.tok.DataAtom { @@ -1738,7 +1951,7 @@ func inFramesetIM(p *parser) bool { return true } -// Section 12.2.5.4.20. +// Section 12.2.6.4.21. func afterFramesetIM(p *parser) bool { switch p.tok.Type { case CommentToken: @@ -1777,7 +1990,7 @@ func afterFramesetIM(p *parser) bool { return true } -// Section 12.2.5.4.21. +// Section 12.2.6.4.22. func afterAfterBodyIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1806,7 +2019,7 @@ func afterAfterBodyIM(p *parser) bool { return false } -// Section 12.2.5.4.22. +// Section 12.2.6.4.23. func afterAfterFramesetIM(p *parser) bool { switch p.tok.Type { case CommentToken: @@ -1844,7 +2057,7 @@ func afterAfterFramesetIM(p *parser) bool { const whitespaceOrNUL = whitespace + "\x00" -// Section 12.2.5.5. +// Section 12.2.6.5 func parseForeignContent(p *parser) bool { switch p.tok.Type { case TextToken: @@ -1924,7 +2137,7 @@ func parseForeignContent(p *parser) bool { return true } -// Section 12.2.5. +// Section 12.2.6. func (p *parser) inForeignContent() bool { if len(p.oe) == 0 { return false @@ -2064,6 +2277,9 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) { } p.doc.AppendChild(root) p.oe = nodeStack{root} + if context != nil && context.DataAtom == a.Template { + p.templateStack = append(p.templateStack, inTemplateIM) + } p.resetInsertionMode() for n := context; n != nil; n = n.Parent { diff --git a/vendor/golang.org/x/net/html/parse_test.go b/vendor/golang.org/x/net/html/parse_test.go index 7e47d11..0b72a12 100644 --- a/vendor/golang.org/x/net/html/parse_test.go +++ b/vendor/golang.org/x/net/html/parse_test.go @@ -125,6 +125,7 @@ func (a sortedAttributes) Swap(i, j int) { func dumpLevel(w io.Writer, n *Node, level int) error { dumpIndent(w, level) + level++ switch n.Type { case ErrorNode: return errors.New("unexpected ErrorNode") @@ -140,13 +141,19 @@ func dumpLevel(w io.Writer, n *Node, level int) error { sort.Sort(attr) for _, a := range attr { io.WriteString(w, "\n") - dumpIndent(w, level+1) + dumpIndent(w, level) if a.Namespace != "" { fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val) } else { fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val) } } + if n.Namespace == "" && n.DataAtom == atom.Template { + io.WriteString(w, "\n") + dumpIndent(w, level) + level++ + io.WriteString(w, "content") + } case TextNode: fmt.Fprintf(w, `"%s"`, n.Data) case CommentNode: @@ -176,7 +183,7 @@ func dumpLevel(w io.Writer, n *Node, level int) error { } io.WriteString(w, "\n") for c := n.FirstChild; c != nil; c = c.NextSibling { - if err := dumpLevel(w, c, level+1); err != nil { + if err := dumpLevel(w, c, level); err != nil { return err } } @@ -196,34 +203,36 @@ func dump(n *Node) (string, error) { return b.String(), nil } -const testDataDir = "testdata/webkit/" +var testDataDirs = []string{"testdata/webkit/", "testdata/go/"} func TestParser(t *testing.T) { - testFiles, err := filepath.Glob(testDataDir + "*.dat") - if err != nil { - t.Fatal(err) - } - for _, tf := range testFiles { - f, err := os.Open(tf) + for _, testDataDir := range testDataDirs { + testFiles, err := filepath.Glob(testDataDir + "*.dat") if err != nil { t.Fatal(err) } - defer f.Close() - r := bufio.NewReader(f) - - for i := 0; ; i++ { - text, want, context, err := readParseTest(r) - if err == io.EOF { - break - } + for _, tf := range testFiles { + f, err := os.Open(tf) if err != nil { t.Fatal(err) } + defer f.Close() + r := bufio.NewReader(f) - err = testParseCase(text, want, context) + for i := 0; ; i++ { + text, want, context, err := readParseTest(r) + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } - if err != nil { - t.Errorf("%s test #%d %q, %s", tf, i, text, err) + err = testParseCase(text, want, context) + + if err != nil { + t.Errorf("%s test #%d %q, %s", tf, i, text, err) + } } } } @@ -373,6 +382,11 @@ func TestNodeConsistency(t *testing.T) { } } +func TestParseFragmentWithNilContext(t *testing.T) { + // This shouldn't panic. + ParseFragment(strings.NewReader("

    hello

    "), nil) +} + func BenchmarkParser(b *testing.B) { buf, err := ioutil.ReadFile("testdata/go1.html") if err != nil { diff --git a/vendor/golang.org/x/net/html/testdata/go/template.dat b/vendor/golang.org/x/net/html/testdata/go/template.dat new file mode 100644 index 0000000..a0a525b --- /dev/null +++ b/vendor/golang.org/x/net/html/testdata/go/template.dat @@ -0,0 +1,13 @@ +#data + +#errors +#document +| +| +| +| +#errors +#document +| +| +| +|

    -M>6v?t3&+$A!*_CC<^E}BWA%A(+ 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%0A}P%G77&n?`$>&wFRguE+P z4=y%7Td7O1+TVDCVD+U~wM4~>%irAM-2N*p;=Yk0bG#%_;!~6t*S^2lc<~pQT$72z zp(Bazm_R5t&KA!JiX`9(=-A@sP(`!6vTPB_E8uR_4a8dU=%8mOV?#ZCXx0 zfP9n?;O>|puAq!Ucke^5wl=G1nqAQpMZ|w%MZ;|;L35kw3e|Wjx-PLIx<0XRBb`N6 z#q$P^n59@#M`zE^JjaQz*ROwC{9j}f{xE{6f+!b|v}_5tIT7!dsDZJ+c?@2}QAO~1 zc@#8)>qd!)8rY`%B_baa$3HE>d-twg`y8b_knTcgnzr>Qt@uMlwW8S*MyFB86d5IdRWez>XmTrLhiz3hDog zcJ*(v;=}E{|Awa?Ii8hWno7)@V1=ww7K{?^wDZVZ|F1^yIiC_m|N3-oxt#dd41ZAE z0b!2PKlP8RbGP@)Z)`Pc$mw2gId5WJD&>Uw$d0&c^l; z2sUX@pw-SV|Eu3=!X$nAX?5`t$L$^UCMSqEllN4oX}Cw2JVg6A%(ZbgNq;BM7!+m# zVglob#zaPkRt`WaHXL?kp#q@~kjJtqkFmafp$2-4$&gr;3Jkp>jBq1YZ z3R7rnqzD6~^)}Ec>UTEhL)dO15-`j>$|{ge76)Z!qt%%O0k`IassaQcoIS+-4|vSAOKm5^2MvZsB|)I zL8Jg7Y^Mbh?RMj*fEHOH1N~l|6ij7qKq-K0191y|AaOvMK4|i`0AdB=KYO70^7FUS ze9{K^^!+u*tN+^$-oR}?$-;sXzWY=ozKeA%agDw0=bnQH-)vpEapMBSE7?cWgIiaA zJv+n33@gCFjVjr3E1?&I^eOHka-&8ZZ=T`GrqoE<61pB^E(>AE($mrj_U~PN)D0Bb zy3e=r_0Ay;R5tO}ADffng|R#d;I{N)l*jx4X`Mh+98_i8j|%~<2104v`OQF%r*#x) z5F4cw*79?4u!`4JH5+RL0>|HN-u>{79dB*N>p@m?_1HA%ZnEB5uQiS&HyPaH3ip;k+DSvz(v_Z+C=Gun6vU~ z6G5i~M5&ps+;?<$hYjT-5o$$uc;`S4e^Bh9`oZTe z)Nm4^7`g|-efN%`o#(&a{F^PX@+)q99XvbVzjb9E(t$T>OkZ;lR%_A2A S;|PJK{}w_Z8gg7~(f&WeR;qje literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf297fbc5cd66aeca02688585a23f98a9f0081f5 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf297fbc5cd66aeca02688585a23f98a9f0081f5 new file mode 100644 index 0000000000000000000000000000000000000000..884b46ff49575bd420e32f4458cdae2a21e6ce80 GIT binary patch literal 878 zcmWlXX>a045QZlS$!5a@tuo0dv%5q~m=C!O?RNW;&}Q%fgM+yb16j3vLm(VBcnrzz z{Boo$O@HHJVcn#Fu}d0Zv6Xm5MBXc zJ+3`uKWER0HV=88r+@i#^l2~qa9vO3zOQE73+K`cG^x4%wAS>7Vnv;}Xy^r-jneFn z^SW)@KYkRu)mP1?X>C}a&%LVpx{MwYB*`*4JFXK(-ey_b5ZGWm)6*C4gWPTQB%e1; zmZfFcVr5gpM+CuN=Dx(qC@hlv`nZS{IJOYaB(8oxfbe;vjF!a}bJ=X4PB31$8e$+~ zs=mv-R)vk$m~gVe37n{jaGHb+Bw=V70?eBRBUmQML=wePkfx|mmu16@s=6S{f^1rj zZ5q2fAhdMZ$-f9v~?GtA=j(MiyDd+3oUA|?5XgB`V-WJug zjZzw9;}3DdS2!;4`|ApSt4f+bTXj3C?M*zf)50xfS+NyAvs|EQr(c{c-D%C!7L&rV zUvO3T>R6Q0_x~=S4PjwPdew2eQE8v5-DW8EbTPI@CWlbezrhPga4br4cnLWYFBx_y z-3@ZDy>ceCzjsd{6gmb4X7z{_H)6$$SW(?DGU#;`5|W4SXE%9AlAZL=+&}yKr?W=1 zQj8B1Wu>O{>u^?W_LHe{rL-yB$Knrz&+&+m^TR(r#Nz4q>x&aY&9E#~$2BRK^GF3O z*d>Wb1ONhvMF>KMLJUIzh`@i{01H6FU5rtHVR2`rvAYwiQ(SIg3S-K`__x(^^jIoi z2bId*U&HnDvn5AxNl^u>aMJxW8I6W7i-t-wC<=z67=RE>0vb|O(aHg`e*0QBhFw;3@L{yG4V20${8KK>6Rc>HAm literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf30493a58dc0fad8c77816086b2b32875cade69-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf30493a58dc0fad8c77816086b2b32875cade69-1 new file mode 100644 index 0000000..167d3ec --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/bf30493a58dc0fad8c77816086b2b32875cade69-1 @@ -0,0 +1 @@ +"4656612873077392578125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c05bf2b6c368beec9fe1ab4172da851e547b1e49-9 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c05bf2b6c368beec9fe1ab4172da851e547b1e49-9 new file mode 100644 index 0000000..3af542b --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c05bf2b6c368beec9fe1ab4172da851e547b1e49-9 @@ -0,0 +1 @@ +&& \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c07ac5a6c29ec72f00d7fe9cfcd9900ebf6fcc1a b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c07ac5a6c29ec72f00d7fe9cfcd9900ebf6fcc1a new file mode 100644 index 0000000..0ef2686 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c07ac5a6c29ec72f00d7fe9cfcd9900ebf6fcc1a @@ -0,0 +1 @@ +-0x3a832B3c2cD67857EB1bDb0ebDE1EAf.0225V_5ZGo_h9QpFgDt5g5np6_G3P7___Tr4438niX_R6q_JlK_mF__t2___4A957_EAxmGZ_8_BF_O0g_8_VM2_cgw4.-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253.0xDe9D94B9EEaf48EDccB4b5Da0-0x0e-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031257318e00017542035 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c4d93c018e1686a8e4aaf0a4dad8d60fecd13675-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c4d93c018e1686a8e4aaf0a4dad8d60fecd13675-4 new file mode 100644 index 0000000000000000000000000000000000000000..b8238c4ee637c2c2d7e60c04cb332c432549c1ec GIT binary patch literal 3 KcmZQ#U;+RD3jhTG literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c64b47ad9a354cefde19e93efca0d656a20fe024-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c64b47ad9a354cefde19e93efca0d656a20fe024-6 new file mode 100644 index 0000000000000000000000000000000000000000..e45f8fbaacdde219dd5560ab577ea920f289442e GIT binary patch literal 4 LcmZQ%U||FR01*HO literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c6f1d808e0fd8c0a973e1b251e93ddae5930638e-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c6f1d808e0fd8c0a973e1b251e93ddae5930638e-1 new file mode 100644 index 0000000..6958298 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c6f1d808e0fd8c0a973e1b251e93ddae5930638e-1 @@ -0,0 +1 @@ +-0757x2cF8a60273074361272e0x2cF8a8E.-9101862645149230957031250xdbBC2aBDA86264514BEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-0xcA3.07047556026031-0x0e-910186264514923095250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031257318e00017542035 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c7fd10d5817ad18dcb798e82328e8a7b087fbbea-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/c7fd10d5817ad18dcb798e82328e8a7b087fbbea-1 new file mode 100644 index 0000000000000000000000000000000000000000..eb0bf142a588792fda15c10f7e22540f36237def GIT binary patch literal 928 zcmaJ;Yfl~^38Bt@x*v$mVE1_i_X*Vm_0em}L6 z`?Pnp5g87f-E`2&2{90XVHhIZe%~*TM36A!@mh5l#1s2x!*;sX?*yh#YfWd~9mU z3sh^%s(LdJLdKx3L!~iMG2(_23JoPyO`-;1hU+K*fkf8>JH&?yIW6Hu;!VD5GXaLy^fL~Twn#}HG%IAKJ+tBPtd3<2hV zW1s`@YkXq+MvFarOv$s$7mY&bV*bB2Qd%*L&`N_+s=oHHrNwAuZ8iol1+`Sbe87{c)k6U zOXMy#|2P`G8_mu~OAq%5A(tVhj=HFj)Me~BC_*xe-fxsbK56=>&!9>SJw-;)apAAr zWVkfhB1i2~9ob>!qXE8<7bQtfvo)Ma>K$;bo z26?5D3KgW42biq=y1Bln+-arLGg*{Q3nio!X4FwBFP-iPlX>ZO z$2UdLZ7bjFv>gjAX)=j|nW*)44aO{ihFsmi)RF|V5?7Kl?$}^k$StYAAM-gN)1AE( zv^@W*y~Fsw1037ZGyYq-*$;btJ~442T65yplHmgA4#=leSP4eM*%|SO$nvNnY`U%z zdBy1Nd_ogClQzvvs|qn$;lu;ZIJ30>U={0tg{MPZ2->AOsOyM?f5r3nfzG->c7eU!UFW z>>VE6t-ZYewY?Ygw@){IuWfCvK*xp%5C9PY3i-Zr0MtL*QjwOBZ4qcO1lVK5#*g{U zNhkflDy$)zzN7p!4bq@F?l&qy?f9U)e|mZ`IO~twqe1GdG#ryTwryFAWlH9?BdMbN zL`o#*-O=$?8q}NPtA4w2T^SrqgKnwTYxQPQe*_UTlcWH3XN#3djyU&~Ua{l~VttHT zs~K&M@v_7#Gm9B#zVCZndWGFexe==K1OOTXN(~GE23e?8n#9tJC}R}s){3FWb$b*8 z?nlbQT8*UVSX_5&5sP7ce+n=$3_xN70E-fX@WRHW?!w5?Qw*)7xN8_mG7cw` zw>uB-SJywj^V}rztVna-eDYv)hZESMwR)#EJv5C^i#q1{ahlerIsY90^%8!o8YaX{ zUbnizNJo^kJnj8Eq|$V_7*n-3O9%-$cilvCLWpS;j2GXBrK#&?I!2U4ttUjQih47| z^fw;kF$lgg`&VnJ8n?Y?q0E6(Ook=%C9wEy9~W DUF6m> literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/cdd398e0ae2a152bcb53d296a63e1e8ccaabb75b-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/cdd398e0ae2a152bcb53d296a63e1e8ccaabb75b-3 new file mode 100644 index 0000000000000000000000000000000000000000..1986e61f01862813fd1c6d987f8fabe578e14b69 GIT binary patch literal 1098 zcmcIi*>2N76a}%BEx-dv@PH7gNFXJe#p6Y4h3wc#x8S5r-6XAavB!40#A%wQwHvm- z;hEpymH&yvbwZ`859JBly7J7OIrrRi&#m{@Zr*?MMS$Qutojel*u;G>=B5CyUL!*7{LzH5nyUx0Vj2eE3buP*U%#-Wqnc4oXq9+o;w@ z{c62A?B|D9daIRDwNr7unqc_ygHB^rEOpc6N1Ms!c)!=(I@_y@W5$zVH)^rtI`w*k z{^*4}thkUr9q7a1vbV98Lga41#}M}W?Grdj#%);Nhm|;lQz*%Z7AOTOIAtOWnICfM zgglOPq^DzL#-}OnjXCACRLq0ukdFTD51K_R7Ft5V4N62BRLBYqy;rKY#t!RV8OQyLAPCg$R~)j$t`+{@vu|&g9voC)_%SUKd~pAWme*4Kn~F ze+mj{HRuz$3DwR>9TE5R#{IhQ`D5_*s^$Ho)>#B#o~DWW2q1w9LKTXH0eX5t>c7t( zj-FSm!<{t1p~$;|_XwqfcDZEVy?kx2ukUWZTK{ifij@aA&gnO$sH2Dz?!j8*y*H6k zLP<)6azIi<1rbsRN$LzCDNt)3*(eC?o4f1t=CmJ-Ha4U*#z^C&35Qr<@4I-W~sVgSZX)Qo`6Mx28F^uBZI!M?wpWuH3z+Er^_o!9($ zHm}{yuDj>AjY+fWr?r0dblf=^KW1!TO!)lJFvfCMjQ|4^(bL^U-ClI-%r>k&xxi;4 HE|>lS=unU@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d38389226ead13791d80008cc5fb1eef75aa0be4-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d38389226ead13791d80008cc5fb1eef75aa0be4-6 new file mode 100644 index 0000000000000000000000000000000000000000..714dbfe3ff93d5d51f73b4e6d4106cd85bb462e7 GIT binary patch literal 11 PcmZQ%WZ`CDVF3{U0Q~?h literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d977ecea3fcbb78028aabdb98bf098594d5eaba7-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/d977ecea3fcbb78028aabdb98bf098594d5eaba7-2 new file mode 100644 index 0000000000000000000000000000000000000000..b53ee1bbde90c7a431a2e4a4901d56735fdfc897 GIT binary patch literal 544 zcmXBP>rR~{3U7>10LCRYV36;w*Nm2QR zr8J&V>^>l+rh$u_(`QMN#Fe@6wdDF<(%fyBnCGvDIk2^M%YT@FgFNt{wrGQXQ8hW{ z4XRk=ZaKhmA|pvEujxXCuXJPKQX&l7H?zDj_OmZX>qOKEu@9$!00CqWLM$Ty0SO4Q zJOEt!iqM&?-DK)wAz!Kq}ep1lgpyv8@SkcEMk0Q;3ph9Y*h4I2eQr1xm~gf z=NUSYqEqQnDl7Z$fxDAPQWG>?h@3b5)M|>4#<3psz7Yjpebw>3YA>jctiY-#%JLzU zeTX#HQxQr7E#9TB$o$7dW<7fXRMt6C(S0FkS8606I`N|yLdZc~uR)zaau%1`HbJC9 z2-E8=9z8_?sUFrLQQ9zOLgtb@iG*kYD7~VH3$Ps?KW@&9eA4Pc4|icWv~P6qom=c2 hx&M(N4#H0-{XLyY$+$QClG^b}p%@zFTIqg%=^vN`mU{pI literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 new file mode 100644 index 0000000..e69de29 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dba30063a9e305d125c83f435e35e0aaa33c560c-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dba30063a9e305d125c83f435e35e0aaa33c560c-1 new file mode 100644 index 0000000000000000000000000000000000000000..866609ecda2ca5b9df92390623b6011419b1c2e6 GIT binary patch literal 1086 zcmXw24O6356g6?RG3%ywJ8P|N(r%rOn@K<(4|rg06^KFe9gT?Tw6FO9)O;JF37Ykn zXQmh3g_--_We(?^d+&MQ{{8zezi!Rv>(8GL=W&ejyW4-BqS5tuvb35inbykF`m<@e zGs`W{%9d5MtfiH3>D}4w>|piu&v-H%{`5W+P9-9d0J&I14nFTJt<1MVdw_{0qpLIj z{IoOJ-%oxFe=3w(0RAr(DmeqgI2+}SvTM4IlSo9Kmj7D3{Jp$%xHDRskMh2;RqmXf z$76%Dd~6nVeLtOc{Y(Ef6!i33LD%)wJD};6-Gk&u7U(m<0c?s5l}3lAF&G-|(5T(@ zZ>#`iWM7YKvRO6}DIObUt5!2_`nB_7wwRt(tb5a)^Lp)kGr|XomlEiV`RBv#qYD+a73}8st`q%;im0& z#*Q%@CY&N7j#Cr_r$PoPL&%jnIl(6)LY)dh_eW2Q#liMP8zD(TZPacDtBoYqvl}_j zLxzN;c4K(4xA~UR<>wzR)}*!HK76hB%ewo0u#tG4hXMsyD7ASBUg1ZcS9nFRc>xg# zON4mL8`kqYO#`W-A}d5xL|G7sVl%QJB7tBc6C%F|lzD=x!y&B)>?~#bH+R8~?rN_F z%H?}7MEDS>ds~!US<^IGvtaO(R(5G)z>O zfGi0bk^>BgPhi7K6}uScc95>05bvRuRxPX2FVLz5iGHXm*wl9H*hWQ=Yw!EaZjpwZyKk@e_Rd>c`j@YS z(+3}r5Kc0a%x^r$&y&|*-TLY6<43Q8A0K+N@9UE%AJ$E8;?1V@$z(hpHz)PUv+;P< zY|K{sS>@B-8+*fPZPE3H@6S(PMCW|8n$3sx+2K&Rf4=*B^;xyl?|)H!d)e+(L9Jyb zfU(?fo%yEYUDQf;vwa*4=GTpj@9an)oby975%Dk zRc!56O7uSGSy!qBfL+$|vItOs<^*6+pBw|rN&-ttrfwEkzGYdasVp~@>V)Z9Dy1d; z#0^6$V1EA1&w89(w&HmbI9D#fWyqk0)-k}fif%aI4IN0!;0ck!vJFs~IX%U+P$-8o z=nQv_sW)?^>rlsk_v^h6A0K}@pWi+I^R8;hFo;1&q~tHJZfW;EQc7Y%=uQEpZybzD z6utx%ixz6Qm%4FU?>IPsXB{L+x9EFVV45~q$%rK%UxeU z9k!Xv>)h$N54fSq6YDh=Cv2Rq%~1s~49Ce)zz8OBxuP@6r{x|PO}=Ap83#R>%_rc& zw0nfL2gOz0pN?MM5gH*lTdEO?sU%2pgb7L`#jUT#!gV9A3xq8bova;vnQwa$TkIotqpe z%i!n=3j;@F2?S+S{vDdVp@>nUQz5g%{^P!3(64Xb885eZz(>tpP0RnF-EQpGjINR= zL(nLp64N-3QimJ4Zy(&0(-Z1kfb3xiB^`QRi2<$v)O%Qvd5hclATh%5 zA3c61$5!k(|E9e9CX`0wXLrk?4`7uh(1Tiym3p6G+k}-??e9}xd{&vgA%ctkR06gYeVgLXD literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ddc3609a7e8f2da5428973c80847b1ae0bc74af7-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ddc3609a7e8f2da5428973c80847b1ae0bc74af7-4 new file mode 100644 index 0000000..ded8a14 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ddc3609a7e8f2da5428973c80847b1ae0bc74af7-4 @@ -0,0 +1 @@ +"07397778125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dde60ed75565b253fc44c8543a788dbef7b9a53f-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/dde60ed75565b253fc44c8543a788dbef7b9a53f-2 new file mode 100644 index 0000000000000000000000000000000000000000..69c00733c46b7c1ea47c5b2b23a984dfca839674 GIT binary patch literal 47 zcmXpse7}D$x3QUpnFRxrxsjonp_ze^4w3VPRweQpRay3IJ|% B52OG9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1170c6fe09522cb50935557856ba9d85c2b37de-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1170c6fe09522cb50935557856ba9d85c2b37de-3 new file mode 100644 index 0000000..f40fb19 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1170c6fe09522cb50935557856ba9d85c2b37de-3 @@ -0,0 +1 @@ +110�-38828388312238828 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1323173b156c91190a3b84ca33c955550404ade-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e1323173b156c91190a3b84ca33c955550404ade-2 new file mode 100644 index 0000000000000000000000000000000000000000..1fd95e0e56573d42985dee7e6b49699ac2f8daf9 GIT binary patch literal 36 scmXps+`pHbfyvCka`)7YJ7?5iG&iz%ujJ=sq(3Kell--@75Z_ z++dW-T?{(6C%sg*eAa9>p;>O{M@ihCKIW>J%p|9&WCY*>-^FFqac+eOZHHS{)3GU| z4EHG$yi9TZ6OqujZO5{G+kZs*YbY@V`HdDrP!clRC!B;1HVYinBwS!+RA+EvUq`hD zX09FEzZNFPY9oShLvTh6gLA^T#yIDUQ=t;mq$V+_$q>XSr;?Zop&IgH5jBE~#*Fw6 zlM*U*rfV3R?6EDPBG#-C@ph4bB-D2Q;vjVmX}nnYk%WdN9sl#zW^7MUge$_t*KZH% zLwwENzm~eL?Y!SR+D@g;j!Tu!-f8x{+nsyX{bsB^FILhwwZ!fYO0^lgYLDludbG6| z*1Y|M=OrBMZCT#Ymy3ydQ_p9P7wJ;JwCc7h%g&@fZUxmzZrB^i>6NT2Zhe?87f%;K zws_th)Mm53yQ;Z`?#WzLB$fE-fuhp5GRXoIT)0rn^&u)B3Ex^PKOS_dP`CwDACdr5 zz^9+80|wa^K>4h-@I2JdYgnE@f>BiffLF#^o^N<4;A!^={8cH&X&C$*mp=Q;mTo0nISgWlfu z*+j4PRfy07sToY6;K8C&1pV)}LLizi#Un{`HNd*49p-w>@QR z^H3!?B#xhK1SGVYL|DF?)B=_uW+42A5<<`58kl4b(@cO9@Nl^E@0~`YupYdfUzEg1 Ac>n+a literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e36bba8cd1c971edf6696aa76dfaf690e21e08c3-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e36bba8cd1c971edf6696aa76dfaf690e21e08c3-5 new file mode 100644 index 0000000000000000000000000000000000000000..ee0ccc0697c49f4c8331392d39cd8c5e227f0e4e GIT binary patch literal 4 LcmZQ%VqgLQ01yBM literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e4862372d6534ac4eb19df7d21840887b8297df8 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e4862372d6534ac4eb19df7d21840887b8297df8 new file mode 100644 index 0000000..1a0c965 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e4862372d6534ac4eb19df7d21840887b8297df8 @@ -0,0 +1 @@ +-.ZohQpgtgpP___nX_Rq_JlK___t____mZ__Og___g.-____.--x-TyLn_iwrB_mMY_z_sI_s____'eVZGohQpFpGPtgnpGPTrniX_Rq_JlK_F__t____mGZ__F_Og__VMgwBBB55BBBB3AAB535353.xBfba-525xdbC2aBABd3BdA7Afebd62357031253Vz0x7Tr38niXR6qJlKmFt2__4A957_AxmGZ_8_BF_O0g_8_VM28gw49101862645149230957031250xdbBC2aBABEEd73801BEcdD3A7AfecbD864Bdc186264514923095703125-9101862645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253958.0210002111-9101_62645149230957031250xdbBC2aBDABEEd73801BEcdD3A7AfecbD864Bdc1862645149230957031253Vz-0x7AC8Dd \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e6722bb760655d9d3dbbdc4f9ebf7354a2461d97 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e6722bb760655d9d3dbbdc4f9ebf7354a2461d97 new file mode 100644 index 0000000000000000000000000000000000000000..5d81322328402038f9cebbbb68543016943f1485 GIT binary patch literal 600 zcmX|;-%k@k5XTY37}3V?zypaS#utg+xjVaivn4!u*S)q9+e#^v9&ivM z|GHaEOg6LG`F@2gMSyZh~xH_sdpVRLu$tnzz>YtOR~ zq+n9iJT+*vm)b6Pod3H3f-psHi$On2j1JP|uOj*SlKb}4qz`8&*bWEd@J=svw7cq} zY~xHy{~n3R4~s?%ve6>}H4!7)BZ9{HaY2NVC@AN{`nWLAAxelhZoM$P=o3eenhzDe zFvp>c0|=}Gd$Kr4x!|Bgce%tHG46F{dy{u=nFZA_3{4Q5%FbT16Q!e^G0YgEBN!8` zjI4@z7MldCRTO0!Mo1m_!R4HHv42?XyUrJPbbNhOOs^Y9H`8%%Hfa@&LH)3M5ar5kQ!!H{ zr}_KtpmAlvy2Xm&0zO^Pi!W)_i_68tuzN7P&y|XT!1wbwP)fN@W$X2SyUv6V`$P}q e_cYjz!7ZIrQ_yLzsfgQk9h`Cv7e`p*cYgq`#iqyr literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e77ce13737af5a84c7a50d9d18a6699fb862c63b-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e77ce13737af5a84c7a50d9d18a6699fb862c63b-3 new file mode 100644 index 0000000..aa0e25e --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e77ce13737af5a84c7a50d9d18a6699fb862c63b-3 @@ -0,0 +1 @@ +c#x ,c \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e85ca8b54d82486ba7462ea0659c42a0a36cdb71-8 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/e85ca8b54d82486ba7462ea0659c42a0a36cdb71-8 new file mode 100644 index 0000000000000000000000000000000000000000..57a5c01a97f5b48d0c6d51d44d1e7c8fb884b872 GIT binary patch literal 32 WcmZQ%U<5-JMixd0i;)4uhCu)VhyXDF literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ea616ea4310406f7893091a96e87e0b9c0412e4b-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ea616ea4310406f7893091a96e87e0b9c0412e4b-1 new file mode 100644 index 0000000000000000000000000000000000000000..672cdf36368f44da75641a181cbe585f81ff4b4c GIT binary patch literal 739 zcmb7?%Wm306oy+>mAa_1=rV86g{`@GW^5@N8xI7MCI*TDE7Fng2^ZsV2?j;V6ZHxD z09Bu%&(KFe>d;mpbl1&Dvp8q||NG|c*f88M{{pd7R%EB0w}=0 zgexdkQ|OE!g9p&66V0kZnVFU#)Zc2A*zMlGd$YUUc!T-kVY>}l-F|cIuV=%s46{f- z(YRr-szxN0iA(J`a$}Qo17njDZZK?E1X&DGOc<(?$f=RgacxH?f|>|BGTu)KJ4@q8 zP)c;l`5D(MSr18=k`ytHxUM?X%Z9fs)bV*<+zmSSt;t1w*$C>_{->NV7E*_14q=2c zN*LA0LA$!hF+0!K%}n&Bz3m81M2H} zb<6;3oJ)WZe&d=o{Vu;;Lu#$A0e9gl!wHNE#)m6dP34viF-U4Dn5`_?9*gR&M%>DpQ38cD3Y5q5*B*rqx{22-F3M^r=fPrie{!(&GVpEJHt=pH4-`=0-? Z=ljPm-)_GC_<8se|Lptl`qfeSr(c0z*uww- literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ed0f1c5ee2700c3c2d9a0914de90363e750c3f47-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ed0f1c5ee2700c3c2d9a0914de90363e750c3f47-3 new file mode 100644 index 0000000..4d56b2a --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ed0f1c5ee2700c3c2d9a0914de90363e750c3f47-3 @@ -0,0 +1,2 @@ +#)~ -@<________?;1bE661d_)+u::!s_]__________`= +Edd1991119v9_v___[_&c1Y+iZVoOaayODaTxoo%uOj DcH11Q._'riRZU/ 888447t89116414997312B2BB738B37e864B186264149239703123V0x7C8jel332mQj5_2_JUB5_-052{0x7AC8bxee6603zzCa4fC--K1K.-Afc64-ZmsVOt-'tqnfVZhQppGtgnpGrniXRqJlKFtmGZFOgVMgwf5aBBAAfbB555xeF.-5-l7YAXuH_TXH5_J__MT2P7C/ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ee481cbb8636f3957618b3e627cc6a56caa1dce5-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/ee481cbb8636f3957618b3e627cc6a56caa1dce5-1 new file mode 100644 index 0000000000000000000000000000000000000000..c97c0b730c172b25b0d0ceab93deadd1b95792db GIT binary patch literal 1593 zcmcJP+mG8s6vlyyQbZL2Z$;`0Jn+Jp@m%b&R33cYX0su?+0D(ZG$>WzABuWVL*u6}%Zr)s z``=H>oAP1STF33;>)#*tlje1!Gc1eEemHGS+JlS1rq?Qqa$m%=xEHPCs8h5H|5=7& z6qn8Z^+mSnT>m;PH=BCYot|$IGEikUkO@!aCuW|R+$8#?{rXkqt3xBJBI7xx7=F8M zo~bHT&`QJf*h>Y%Rf6t1_d%Y|S~8Myt*e-y z#S%K5Ldt%-*r{A`l~C&Dif}?X)ldzMT57$%*TC-UKz|v17b$o@)Hn@JX^+)EM?=J~UrsSQb%1POkDw5E3Y|GKqsfRMm~QwB~Vw#8wSOz@avFn!f6-@EJJVv~t4@8Q17 ugR#X}mHWiNV67mHk_=aFjyYVo5zB~=os6dm$~*ZoS*^Gv&%Zq!KKm2V{KI(w literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/efa3bc9831786d0e203957fd2ac2c4de9d5c168a-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/efa3bc9831786d0e203957fd2ac2c4de9d5c168a-2 new file mode 100644 index 0000000..a34c4b7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/efa3bc9831786d0e203957fd2ac2c4de9d5c168a-2 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0121676050a7bb84ade5c4783407e0527ca88a4-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0121676050a7bb84ade5c4783407e0527ca88a4-3 new file mode 100644 index 0000000..a9c7d6c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0121676050a7bb84ade5c4783407e0527ca88a4-3 @@ -0,0 +1 @@ +160798828121136868377216160798828125 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0bd04a4f5ccd427cf59b79e2f67caafdbfa0233-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f0bd04a4f5ccd427cf59b79e2f67caafdbfa0233-3 new file mode 100644 index 0000000000000000000000000000000000000000..67deef393ed74b18fe7c0b7ebcbff4442e5cae10 GIT binary patch literal 792 zcmcIh`%}|E5LN*d(2g>SicUoyf-@vu?(!VUFbz#<)25F!l%~KOO-qx$LefVXs=~kS z1^m$;^=9t&c6RsM@7rD4yxo5O`pdgti`&_``gn6~Vg38|{+WZK z_oGuaPW|kpH-Fs?GG=e027YGZnt^kao&+!F56!V-K6=0L`PJ&9uLHI3y-l3CnSS;Z z2VoG_Gx?rs7jYqO=;J}z8+#?Aqx-q>pr}pXXoY(Dve++XHNV#J2Q|OQdMA}ixp4B~ zHfOq~X4A3RP2QajH51Q97@x;tIBc}5v*=PZ6&^K|_Eq#M#8L<%ni3#DNCXrBLhKA6 zAOOTb5FSC2)DlQUK}jLmzT!n5@(=;(KH(|#!m`?Qwd{Gvw(A|2jG^1naSo?39%FI_ z$8}7cqK$D?v!`v#k{d`yZ3{v~8gPgv#8{=-lv#^wP!tFSQe_O0=yqyY=Y6d9b9fNJ zK@wn-0#=e?geqd0-~yX`su~oV_LP+vz(n*|j$x&UBX>`d17XXOi4r-Ll>ewi$LTM%RvYQ Xo|8C^febIvtaDSU4M)LjR#$%m%huX? literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f2a68d20b1e145bbf69037f17685e0adedfe68a4-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f2a68d20b1e145bbf69037f17685e0adedfe68a4-6 new file mode 100644 index 0000000000000000000000000000000000000000..4c59fa1901ac5a880db5faf1e57e866b94ea8532 GIT binary patch literal 11 NcmZQjV`N}~AOHc$05$*s literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f320b3ab9e260a1bbd378762c54a8e23f794901a-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f320b3ab9e260a1bbd378762c54a8e23f794901a-2 new file mode 100644 index 0000000..af5585f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f320b3ab9e260a1bbd378762c54a8e23f794901a-2 @@ -0,0 +1 @@ +e211112182634814453125629739CFeBEEbaE355271367885009293556213378906257fb-053440.- \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f5829f8a97a0a1dc008752245b460db0a0459c03 b/vendor/github.com/klauspost/compress/huff0/fuzz/compress/corpus/f5829f8a97a0a1dc008752245b460db0a0459c03 new file mode 100644 index 0000000000000000000000000000000000000000..55240e503a2a94303ff8c1bcc950b2adcfd71da7 GIT binary patch literal 583 zcmb`DOKaOu5QSSxp^MT*m;DbC_ukQrB)O~NZ$^=lP>_JT+`bcK0qg17(Dg}}t^X76JZOoGact6B!HMthNqubNFCPokSW$nmJ`oxZ%wxp3&zMm+tX` z<&3{pvfyQdv^er{tvg&u*5FQ;Jgy49XTvmvKu5V!+K!7jv~3}?cZMs4WKx9ERUlln z1xSU%F!KYI`o7kM4UUk$F2JtJ%puD!a_I~!7E0^s62#r$YI}hb7FplFee+1 zd%EwsWIVeb-NmQPV#pBiHb}J&y($Z>A}7mI_+7NQ2c{4f4&PQJz!30_a8#^Jd&HKqpgB{y>zh6#-#4lf| z<7B(b(tfREJJERN+&O2?_~X-;7cU?E_$5CY-TOTHI{H|zKgicFO4;$GSLpqcA57kl zK9p;NJDJhjH-G;1`pK6}A(bi?dM^r@;-+2sw0KyqH}kRbV3CWNW-ULk?Xw@g{`~eV zf8KuGALrIj7X4~$GtBi1`Au#=u3ua%1C!^-~yL&ZhNTWmwn_E8B8=d;izV{=U>&ZL`&8W;AQx``q6zx2OMSzr7fB%DG(z zp$@}wb6;9bmaSE3HeNrdbUt*ZGdyv(DdL&a_GU9Vv@65x_K&BXS-(6lt*7%+Z8;sZ zDvK<3Jn0l0g!@#eLI_1L%J9Mm-Xg9LN|>OGkkF@|Z#fS0eVcos8t#MP)4`j-J9a`h6TVH+l5KGgU@0Qpi$`U0&K`(%rpZ@g+ZBt z%?TC{4MQ4EAcdpE-jPtpirSK)9#GL1fRex@g?JR>rXh4N!y~LrL6IDhX>Vtcs8_@! zm~rG0dXhTQGNq?8B2SD0zw26>^t#_A8zk{vgoK`ZQ=cHR`wc=uAn&*z;(gT6vt3V=(3dQ8%$3L-A}m^vviefTAW9QTCTQ-P8KcI*v;DDz&z;$R#)RZ z43adCLkTS}<@h8t10qb%PH~?miQx;+QG#NybXF??^wqP=%e$9vet)hK6{t|7sS&2) zJdsF}I+khM9!n6_{)dNaC8Vb&u5wW`OlFP4v0gg?oPtLw5F*kNLG%bkUc;cEiAYiP zsNnJ3Yb-@!1~qgA-Ns0mbZpx~TOEhc)uS<;y2Iv9z(m@&WIl>4u1BgUL=|XWq6q|y z#HO02ag>U19e=1wFruQkl%UsfHe9D1i@1i|Xv7rX3zbtn_Q^n^rwOVzBfQc}{)_Fc zwvN;P&*J;aW4f33mFzi>-mOdaB0}K6Yzv>b-R+g!g9!&l1f6l1vB8; zrnLo_0~kPnrwi38c!Ic8NsxqK9EGPkuBJfwRn53DJ-R;ndY){bjC^n37(XVV#fn|1 zYSrcz#*(yPxM;#+41CMrK=eIL!%RgLTY6uE8l+(l3=&7Z-yYJ2wLd11H1NUdDz~j0Y7&;>w=7x#%Ch>~%CmCqJzC KyDJalQ#Sy#vk~Y3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0297e0b01e8ace9ec3a22311966681bbe06b875f-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0297e0b01e8ace9ec3a22311966681bbe06b875f-5 new file mode 100644 index 0000000000000000000000000000000000000000..91d73488c426e7f35ce9baa44ceee84fc0660d14 GIT binary patch literal 2 JcmdnR0004Y0J{JH literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1 new file mode 100644 index 0000000000000000000000000000000000000000..84338601e306714ebf57686f1ae27adbe2e0a4c8 GIT binary patch literal 1278 zcmVAGJ%+CalV3~8zqS!=5Kp&x= z;^T3-P?)eRWI~}1jSNiXW8)z4HE!)x%EPi+Zvv#QxTw_fOR zo1<&)9zUsViw;PD?3zDbZqDr7o@*O9hR(V3=H&*rJ>G5Xo`Y_kd+xo*8$r5v{VjWY z+bDAGg&w#4NmiW_t*i@^P&TdBG`C@$rYR{EscN>~3msatvMx+QNvDa5WZSzP!N{?r zD0FG()(d@`n?HV1v+8^jt*i@^P&Td8Y%4Xa(=;WW6h~%NvvqF0(6_ny<8RwSmv(Nw z(6_lcORY|cRu?9rY+9$bQrBscl;TKLvvqF0zRk_~+cp9u;DQJWM2H|k1^lj|L1kbL zSVUF7;zsy#lBr5xOlEsgl1j7ng>VGRoO>3b%cbd_xssmOtI=$w0_3%1(`($2lm<2Fav(old_v~cg#aWx%_J!{y#J6{QqzKGjJ9#ATSl4jEKqvY8{3?}DHm%#0*SXi16DsZNx|*WsRr$(xo4uDe zf_QUx&*pA!kKDb|OG;X+q&0J=my|S%LYGRVq_s*~v(SY~NwZH#fI#?v4F!!51*MbW zQQ>L$hzMOWNPu`yE)JQ_1_NgS0|Haw$%v?cJR23z!{(ETKmi>K77!Gn4hIK?$Krv- zfy1N0qVVx#G{`_Su)+CMG%y(*jmpOa$08)rkx=kpc*tB#fB**+p9_TvOGn1X<^c;( zd@d9wEDIePn99c{!T}iQpm^wju;`#zKrl#nJ`u7^02L%y9$+{=G%P+II1mq;2Oo)! z1crkG78D#D77r{O4HkuphzSS~Bsd=o91WBWg9S%|WrG311_Nhf0mXv`2N)C}0swF@ zO%)9hQYJ89R6Ha!Oh`O9fZ+fL3JwPa$^;sUgG546fB*y*G++T2U~r+3Kt;rZ1{VzI oR5TbsL(z0N3l#_w4Gl<0Y;X~Qiw7)lanS&Q01SWv2oyxHL7kjj@Bjb+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1-4x b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04bc4648208f40ba61ffb9a929f760c24101522c-1-4x new file mode 100644 index 0000000000000000000000000000000000000000..dcd1f7ebecaa417ee01a5b6057343e53d3f0ee80 GIT binary patch literal 1285 zcmV+g1^W6)Kxe=y&ph+YGtWHp%rnmi=fngs0~#$Y(MGnENs6SL$hzMOWNPu`yE)JQ_1_NgS0|Haw$%v?cJR23z!{(ETKmi>K77!Gn z4hIK?$Krv-fy1N0qVVx#G{`_Su)+CMG%y(*jmpOa$08)rkx=kpc*tB#fB**+p9_Tv zOGn1X<^c;(d@d9wEDIePn99c{!T}iQpm^wju;`#zKrl#nJ`u7^02L%y9$+{=G%P+I zI1mq;2Oo)!1crkG78D#D77r{O4HkuphzSS~Bsd=o91WBWg9S%|WrG311_Nhf0mXv` z2N)C}0swF@O%)9hQYJ89R6Ha!Oh`O9fZ+fL3JwPa$^;sUgG546fB*y*G++T2U~r+3 zKt;rZ1{VzIR5TbsL(z0N3l#_w4Gl<0Y;X~Qiw7)lanS&Q01SWv2oyxHK@q;3WUA5^ zli6OBq|$7CAsoRn=bl9|Dgt`yDLx*T3x$b=OsGR615^3fILLdh!HpoZl3dUwu;V2q zU1b|ZDstc)I_KW#g6%efv~w@?xXsbId;BD;vU?J(tP7J+Hm%lNsbQUxPKsw$vvux; z9=AFA<0ox&?u8z=Ir`&g)%j>;U6_QjX`S1!PDv-lvu5ku3q5Xg^v7?bhlVMaf6Y3) zWd3I+olHLTDF2@~{w1Af;4D1GgLq7Zr!yk{A7-0DLPYt*s5oQHAnn{9o1^o@r0k~L z9rMsoF8>;b|IbW1|Nk5R44efF2uy`1Bcd_^c{Cf92?+GC`Ajkw>;VsrL#DIAuz&$k z;mL>qJzUPc(6`wize;750}n(DIJaKtahs!S?jAp>S#`Q6(aO3o31!o2O|z}kuujvI zbW$9dRn6A9^+J!^99?tw_(^SBbU*@R*ZlEvb7trET-(Sobk3bOFE_aD@or=H9CYj4 zbMHOg2-3alZ`s@1Mv-$b^tkO$vg(v*WnGwrvT3!Zxeek@4x=xd%6i2F>t#j-3ZEnurwhAGJ%+CalV3~8zqS!=5Kp&x=;^T3-P?)eRWI~}1 zjSNiXW8)z4HE!)x%EPi+Z literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04fe6043558c921672856d1d9332bb41b7d64087-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04fe6043558c921672856d1d9332bb41b7d64087-2 new file mode 100644 index 0000000..cf340ae --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/04fe6043558c921672856d1d9332bb41b7d64087-2 @@ -0,0 +1 @@ +@ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/05575bdaa6ba33f22d304f9f3a62010e42f76acf-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/05575bdaa6ba33f22d304f9f3a62010e42f76acf-2 new file mode 100644 index 0000000000000000000000000000000000000000..c5d688a1241617dddf2a714b2f6c4ccefb26afdd GIT binary patch literal 90 zcmV-g0Hyy}z{X+yAHDYff9b8(Upwb17z<;e*}z$om8gg?(Lh3n@+_REv~RosOvI{; wJ{D6hN8;d87@0}t1A3`MAdux0QA(SML?kLAl6Pj`olp+qevYum(ocS{drEsOvH$=8 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc new file mode 100644 index 0000000000000000000000000000000000000000..1514627ca8027133156d775b2a5967e08a41ec76 GIT binary patch literal 501 zcmcC)Sjs8GV{m|hna3c(fx~v!#S`~-Z=C#h@AOH_S#RAgSlM|&&0FmEzo4qP1s*el zyfjs19w+S8N?f;rg=IlQ7uTD&mo>~M{(7%(W?wD*y`SaJkF-U_Isr4cf1kK$`SO47 zKR%w_d2XXa>b+x+O?RB=VwMSb7@~c~*jpl)KT(0_ki`Af?)_%@t9luFn$IfvE^V?GQ(M?)889-CCc_Ptu<9`xEAxrZAX{I?AX6c zs=NN`9M$#twdJ+tGNJSTl6{sg6>^>ONh;^;(fpRx9h+}n^-o$vs(Kb44JiwT11%|x zo$c46oZT#VQj~K4+jZ4!-FaK`t9(Xb%FL198c0uwWbppu3~Ld1-Y3==gm8xISE z(@l5(+6&*mfA_Cwf2(xl)Y+2!%qCkNnHO!Y-XpTz;N|72zK6*=Ygq#0ntOZi)JP;4 ztc*0_PWxV=nU@%pq@&t#Nu!sIm8YGxqpgXt@c}~%M_XsdSA~ZcW*oT@b?twVp5?#) Q)4%5JRNXmMLEDiD0K0bZk^lez literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc-4x b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0a7ce59229caf93ee64d5a828aecab7b5e434bbc-4x new file mode 100644 index 0000000000000000000000000000000000000000..9c3c8124e15a9d9fa5265080acd4943f562977c9 GIT binary patch literal 507 zcmcC)Sjs8GV{m|hna3c(fx~v!#S`~-Z=C#h@AOH_S#RAgSlM|&&0FmEzo4qP1s*el zyfjs19w+S8N?f<0kfDMhl|hK_%%+6$|L2c}lGu!wkG@fArpYBd32< z*XP%kdC5N{ytN&tTu(?=HkW6U@W~Q8+jP@5t}A-R6bWz6MJ8U09T^WNGA>$};Gkf^ zpxBhClw|8+VWMWZZQ9rUbG-Zh|4-c;o#&aSdcteM+MPdo3q%XecK`D9nbN@M%FNC% zV}g#t#|u%}Cpg+0eU`kv?>=$8S-JJ%f5{((*c9KbI+(mszJIA;MC_l?wDRvFzk}`^ zTC(N5;Z`5jsR~}1(_(dfym}c$r8uRexFq)IEhf|)YT9?frA-Ld)RRsUVfZ=462>c4wlvew5p_Qyh^v;ti; z*B`tV^T%yRm&NSZzba~3M5t$BS literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0ceda9053c751bf974334c7c1676832feea92d69 new file mode 100644 index 0000000000000000000000000000000000000000..0b765c8073cdfa4479975919d59bd6816111a04f GIT binary patch literal 1569 zcmV++2HyEn;0TCn0>A?gJn+B+4?OU|0}nj#zyl9F?D+L3lU-;f2qM}+sSTM;0t|tH zh-w(9xLaiJUqGocrIb=io+t8(4t$`JPq+vPKo#up>jSPh9Rr!qU)sF#hb*WOg*jbV z9FQs1@<`AKNq$kPkn12L%HqQRlaM@vYMGc)uI&FqKjw7dtX3T%nTMvM)8TYHTpg=f zKaUY<)0z=7Zr>8i6ipRzUcQX^niy6l65T7RP%0!*1gk^ed7DIP(wsfJd$xoHwh96W z8am7|J(>SB8cGOsSS- zl`4srRb|x?VhMd5gejJI0TVYL5>yDQcNA_|hG|R*!@973-Rni=y&yP>a<}18GBB;g z2yn}JTt06_I z8a)30U(NcF=Iv|gDOPb_K2WSRyAAfeO(Hd^@9ideNZ@dC@?ilFjX6eg|9zWrn(>n7 z4FqG%YEohSRR&ENu9h zlro=6$bvduKq(K0WyR4EqWU=aB{FP)kW5HC*uXGRVZ!P6@cje8h7QDJMB_ygl7N8) z9ymt+f4t=Xe~_O}f5|!i5Y@upsJ^noFIeY{EwDlUsG3t>(d&T6Hy zn9$*jY+4a4rpgP$0+B_qEOdxC&;W;ularGN9Qc5NVHFfS3Zn1}O-i5ArV_HC#0rMR zNm*7Y(Xv{pLJq>p(nw?(CNLrKppL3H(rjRusBp0XgV~@O(dfKht}g)t3oh!&A`@X{ z7>-2)4H6MBASkj33*mtVI8>aRgkbQ20;8fB3Q2G|)^?M6e=2D3%Gt%4mQ} z1hEE!A+C3%nAV!X5K{`p6v{|34k?t8qC_$t8`rM)=DwMdDU^FBw=DBxQSi(b*hewe&6WjZX3PPquw~GayNG8?#`JF$JFv>XY~Hf&uQJ``Z^s7UuNS`X*vuS3g|RCE|2HKm4FYA>r;tDZR&Ko TyPE-?3A?gJn+B+4?OU|0}nj#zyl9F?D+L3lU-;f2qM}+sSTM;0t|tH zh-w(9xLaiJUqGocrIb=io+t8(4t$`JPq+vPKo#up>jSPh9RrF1p8-Sxub1mfz`%lw zI8061_^@SH+qu60=Yo*fg%DI(yJqnLZN7y z1V>F1X&^zYfnbR19Vw=@W-!E*LNSFhQj9|iWuz#PjK{{c>%F;ereq4`-U&J9oY`<% z84*s4(gHz25$Vvtz4_)Gf&m4H1{h$^6QPuP)T1AzG^-MPDSX2UVHJeiis zrBP`*5!&==A|h0(vE|WpU)LGEfAe!%_qe`Jhr*ZHcvPAW!-WDmjgHIX`EVuR!{ho? zB2k+*H;kw|TG6w*4do0|Zbk zfFTh;(178AW5kpBFV6sZ{_&FkpzW?7aRoIK#b2Mi3Wpx{vugU+CM9uhd5oP1coLt~DS+<)I@oMyb_c>}>1vznBc z$}Dednv`udiK)aaK#xQkC6-xhxp3P!?z1*D5jn(;5Qz-SHbfBIB$xy+NMbXvECOS| zVhQHPl2WQIV5!7blT@p=<`IeWL?bZ7)FX{3oTQjUp?IHYq*%ivPXvY(NhLk%F9D(d zzd_2~hDV7}+f-t!NvhSh_1@ehuHFo8cq4HwF^S{8Zj`nqwwlyx*L&aH-I>J_-z#ms zEoC=|Yn2vP*;n?hx5~fk#FARU@&7O3|1W_5|NsB*2$|1c+Pw0IET|EMIbB#BkSW#j zNYDsLeo?BB>mVb_;==!vkUWEGnV3?p?EgbQ=5*n#RvjUkho+;`;dDG)9jjSCj}d9p znh`Q?-xA9dO%-uozKr>r7*-|{-7Bh4DkM<^t3%&;n?!2ToISgHwuA+?3IYfkI?ORW zng4Q|0rEVf1hj$R6K1ij0*=;NP84n%$9*<5DP=yTO(kSOi51N0!s38Tsg`AxDv6d= zWz`X434I)dDVBHv6E`0cR0ykg6mD3CX-o;jy0CuT>qX_gAUKM0x8YGTFs;N0aLajI zK5s=ju%rI)^Fry#oGc)3|PxczzB5Hn;_f literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 new file mode 100644 index 0000000..5908a1d --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/0fcf0d8fa929e950029b365ad631e876ec5f3c47-1 @@ -0,0 +1 @@ + 0_$J*pm7'j.t R me$b;*ArT~q9v_Y2fq,kq0ۀ0#MJҹt S1/0Q7Z-yY`%^a;{lk~Nj($orEssAEkmvHn$YyPbPCgGq2p7Z-yYJ2wLd11H1NUdDz~j0Y7&;>w=7x#%Ch>~%CmCqJzC LyDJYPL_i7v251w} literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/118873131212b4f8e4f2b7aa9e398911bf83fb21-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/118873131212b4f8e4f2b7aa9e398911bf83fb21-2 new file mode 100644 index 0000000000000000000000000000000000000000..a4ef342785ef226bcc3a9402ca17a85186593b3f GIT binary patch literal 9 QcmZSQX5e7pWO%9$00QL!FaQ7m literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/12a386209a550aec21fbfa0b2ec8c066fe131db7-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/12a386209a550aec21fbfa0b2ec8c066fe131db7-2 new file mode 100644 index 0000000000000000000000000000000000000000..d2eed5c766074a49739ad574c5530792753ef76d GIT binary patch literal 12 Tcmd<$VsK;UX5e7pWOxby1r-5f literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/17a53cfc55c261af6e258f0effbe34a9d0c3a117-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/17a53cfc55c261af6e258f0effbe34a9d0c3a117-2 new file mode 100644 index 0000000000000000000000000000000000000000..f73395fe22fdbcd1f473c7ed741b65d1c7cf856b GIT binary patch literal 19 acmWe!z|PkqGehitQ8*VDgBv?H0|x*zLIg1Y literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/182516c486b2eafc720a03046af1949a758ff7b4-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/182516c486b2eafc720a03046af1949a758ff7b4-3 new file mode 100644 index 0000000..00b2a2d --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/182516c486b2eafc720a03046af1949a758ff7b4-3 @@ -0,0 +1 @@ +60616263646566676869 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1e23aabdf832d3bd167105c98f4931313e0df945-8 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1e23aabdf832d3bd167105c98f4931313e0df945-8 new file mode 100644 index 0000000..c30f00b --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1e23aabdf832d3bd167105c98f4931313e0df945-8 @@ -0,0 +1 @@ +@eEEEe \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/1eb38d67be98350dd6ce98f72e5b1b75043ce8c7 new file mode 100644 index 0000000000000000000000000000000000000000..7776e2ea671857150d1d420c6faa9b70da3d3635 GIT binary patch literal 78 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 l03HS{6{r7Nkzki^Cb2{x?m*l{{bo#OKt!F literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/234ec5ad1fc105fcc08523ff91bd8430284aa1f3-4x b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/234ec5ad1fc105fcc08523ff91bd8430284aa1f3-4x new file mode 100644 index 0000000000000000000000000000000000000000..dc1291af5a593711a0ccb3a0dc98955f16b32399 GIT binary patch literal 100235 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�H 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/236bd270f4d36e14eaf41daf5bf33e55ff5f463d-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/236bd270f4d36e14eaf41daf5bf33e55ff5f463d-6 new file mode 100644 index 0000000..cfb3230 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/236bd270f4d36e14eaf41daf5bf33e55ff5f463d-6 @@ -0,0 +1 @@ +eEd_ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/269f2e5e3b3b1acba92aefd0a49444d0869af5ae-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/269f2e5e3b3b1acba92aefd0a49444d0869af5ae-7 new file mode 100644 index 0000000..bf3464d --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/269f2e5e3b3b1acba92aefd0a49444d0869af5ae-7 @@ -0,0 +1 @@ +eEEeE \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/2805bdad6bc68c3c6edd9344d658b6d43a8dbcbc-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/2805bdad6bc68c3c6edd9344d658b6d43a8dbcbc-3 new file mode 100644 index 0000000..fdf25f8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/2805bdad6bc68c3c6edd9344d658b6d43a8dbcbc-3 @@ -0,0 +1 @@ +Z [ ۊ4I$99 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3187c5cc2c8b927997cbd46e9328581620116613-12 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3187c5cc2c8b927997cbd46e9328581620116613-12 new file mode 100644 index 0000000000000000000000000000000000000000..44c6d886aec74a37b8e0959f4d4ff5259b7ca6ff GIT binary patch literal 23 ecmbObqNKpUz#zcDVDz@iR(ETl({ztM0Yv~n%?2O< literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/34e0f846cc18c5c0a6e0334192411dc2c6a1c719-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/34e0f846cc18c5c0a6e0334192411dc2c6a1c719-7 new file mode 100644 index 0000000..f988976 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/34e0f846cc18c5c0a6e0334192411dc2c6a1c719-7 @@ -0,0 +1 @@ +eEd@ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/36971f66110d363f2a217d16bf1913475c25a862-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/36971f66110d363f2a217d16bf1913475c25a862-3 new file mode 100644 index 0000000000000000000000000000000000000000..a025cc67c2f828e839de9dbe4a469ee687667cd2 GIT binary patch literal 90 zcmV-g0Hyy}z{X+yAHDYff6=YhUpwb17z<;e*}z$om8gg?(Lh3n@+_REv~RosOvI{; wJ{D6hN8;d87@0}t1A3`MAdux0QA(SML?kLAl6Pj`olp+qevYum(ocS{dqVpxng9R* literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/38729163260fdf7a5526f17de3cb34f02661e8c9-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/38729163260fdf7a5526f17de3cb34f02661e8c9-1 new file mode 100644 index 0000000000000000000000000000000000000000..3260507a8fc5f711297a6b98c4b490d8025c2730 GIT binary patch literal 28 icmd-)Aj;;csc9`!%*?<7gzqOXI<`u1Dw>)qFaQ8ia0O=o literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3885c38b78f31c98dd73bc1fa7d6dfe467eb0fa4-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3885c38b78f31c98dd73bc1fa7d6dfe467eb0fa4-3 new file mode 100644 index 0000000000000000000000000000000000000000..ae0f633b16f2940736ee4ec2479875a950a53825 GIT binary patch literal 90 zcmV-g0Hyy}z{X)9jvM_Sz4rfq>8;jMJLf4F3uB?#02%=RsE9GqKthM|ES#sbZ@d6Z w#Hx%w7E>-q%^n8`4n}z5;8GZwN#+B3sYD=<;ehew+H3LF&ow2ulNUZY5IK43iVlN|4o>Z#H0LbelD~(+=g6ua qJF#Fr_eT$cBxZU(W3F21qA=m9NTAp3P8Ss|rAg&!_vZ%iJpurfS}*1R literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/3f85a2df398429128e89cb13f51f612645550408-11 new file mode 100644 index 0000000000000000000000000000000000000000..7faf9be2d1aff0ff4819c12b3872012e333c9baf GIT binary patch literal 15 WcmbObqNKpUz#zcDVDz?1KoI~JE&~Ao literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c new file mode 100644 index 0000000000000000000000000000000000000000..1b1a7348b65a2133ec8f1767980e5e76551dadc8 GIT binary patch literal 156 zcmb12U~J&IAeWr|?f;dyL#mTz&YUTvd+q-YX?-@e-Fx1;#7iEyc)IfSqOJ247yfhT zStxXDqJ|TftHN=^?O{sKB^nJ_d5<}W$?u)BT`%glq|hp6h6xpg0d9wOZ{e9zpu>2z zQR0w?NTbEG8A%2RRj>Z?zFV~`a(1?jU2x#XcwQ#6;)HJv3+FtVqnN-EP!jRy?*H&f GiwXdmxklaq literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c-4x b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40b8de701a171fddefdc4459023121a1e605b16c-4x new file mode 100644 index 0000000000000000000000000000000000000000..3c919cd27e34180c66f804e867b4485ed1783727 GIT binary patch literal 164 zcmV;V09*eWU;%&(&>mxJ_W#sg!X=WKnVAwT*8jL0F9sn1A^;%(S(|G-K2uTgUkw5_ zb71y>p`7BJAz%nlbXfe||5uWta2Y7!SOTg8F@%vQ0&&bS#b7KxdO2@hwDvP3)cYIU zRdoaA)=K0YBM_#b!5GNmqnGp6MQcApLUjND5-$$QNO+ePCcC`tL|+-e(aU-3qP3qP Sq5eROp%TWCC_)NFAjb)VX-Aa+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40fbf19f5ba46c802a2755c71c852b92fc334dd4-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/40fbf19f5ba46c802a2755c71c852b92fc334dd4-2 new file mode 100644 index 0000000000000000000000000000000000000000..b560eccfa36c346968c3e641c733680a55b333c3 GIT binary patch literal 18 OcmWe|Tylm11pojWw*kTc literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4106d42682c6b5f9f068148a3d94f5b52d9a2862-1 new file mode 100644 index 0000000000000000000000000000000000000000..05f72a030aa17ae8034f30cd52942db60b503a2b GIT binary patch literal 943 zcmV;g15o@>;0UNX0>A?gJn+B+4>Q68ILt7^3^U9y!*{1vcEU<*+jbl#5{p$6uq?~6 z%<{ZYDNICuK*&knyG!ZaPZ5AZAe6KLT!apo2snt^Lwl1Lu<@cO5xts{#!c_$wUK1b zq?jR=WW&pX%{SY!wB^0_T5GR;aN!dVG@uab&kc2c&9TNPbPd?(3(+bKYny1sFvcKx zejf;y@Og6Th)y1nG_Fu_qtd)UBNU5dbg@q8=n`EWA|pw(;AFi}2^#7Vm8?iwmrduV zZ5z8eXFO0dt@M1&j%U3BV+f;FAh< ze$6O!ki-6uF8f2SBE!o9B+iplM>r zh43V`k(P)&V1O|Bq(ERQ)kmb2;zZz(kuDVz3ov2WI!SGKq^XQ-r8Yo3NNH;FkzqPw z$0Ni-g+ivWbE(+GjXclO$s>*{aq|M9SR|p*bsAk_Yqapa*SSk}H&IAhtiwYH5sSOX=1B8Xd2uMN2K?aA02n%3b zX0wzC6o<>D;=)pym|(G3P%vQQ0Yf$dQebgFbv!bUEF}WP;o`x9A_4*eA?gJn+B+4>Q68ILt7^3^U9y!*{1vcEU<*+jbl#5{p$6uq?~6 z%<{ZYDNICuK*&knyG!ZaPZ5AZAe6KLT!apo2snt^Lwl1L{Q%bhzyJ|AWTZ>Q!~#qh zwoXzT9%(8gTd55Y4^o<%d}Nr8*zpLlP@#}%>|81~aU;+3bn=MfO5D6aC>BX*be%?* z*cvUoI4ax4W~oe=GA0fV1Pct$YV!i2NFKs4$BSskpFICMH-c78DHFc)*a2fD~99P#urV zBTI=uakzM}pooBgKzYE30*VX^q(p?Jl7s(8zyTEC000DD)m+si%uHFvv<+i?eqRZn zC+G+55UFh1#tG3S8U)OetpS6s=GK+-E>vB&smzcj^VFHrlu^r!j7*7)nKGn#X4JZZ zg>cFpez96>-sLvGudHFL*1G*+2#fvyAN>CV@c;k+{~aIye;9|SMY_yVQRe$HUnUjJ zQX&lCfH}~B0>*^F1YiOFhH1mQXnvu>Lb!haRS%tY?p7g*1NX= z+hg6)2t}{HUAMt)f*SJgQ!NLrUo=cjEOyE$oEcy^^Q zO}U!0X~xJMemYh$TwFB<$KZ$N_jsg3`|3Y`H5{kHDsyCqpN>^c#NlhXsva}) Z`Q~lGE^pF2Kh1%4a~cFMSn;)-#$FVT$14B; literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/43726b29460c5060782f19cb0facac8443ad5d0b new file mode 100644 index 0000000000000000000000000000000000000000..0a50371134f0808934dcb67e1468e5edfbdf6981 GIT binary patch literal 513 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/44678db801ad65c4ba51cc5e0cd9095852f329cd-9 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/44678db801ad65c4ba51cc5e0cd9095852f329cd-9 new file mode 100644 index 0000000..d5a9607 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/44678db801ad65c4ba51cc5e0cd9095852f329cd-9 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 new file mode 100644 index 0000000..a6b6e0c --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/46fc2fe81fed8fdc49861d8a8433560c5a02d503-2 @@ -0,0 +1,3 @@ + +)U@<,H- + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/475dfd55b54d9a0a4287ab8b952f606f2773a49c-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/475dfd55b54d9a0a4287ab8b952f606f2773a49c-1 new file mode 100644 index 0000000000000000000000000000000000000000..35becdfca2bdf7d14b58a7d3f5ab15414163d83a GIT binary patch literal 1122 zcmV-o1fBa*@CJx#0vdRjfrlA*n1P2Gc$k5Q8F&cc|No5}H>CvtNIfmJQ9_qUj=_;k zS_r0@T4eVQ;K_DMDW#M=Pvjde%##!D0G`Yr^U2in=P7)o>JfPXc>xvyKjEk>9B3ve zB3Kb16w3r+Wi&vb&1t0J+KfsdSEj@oeLfFROke^OnF|PX3QM023Uj(}QYy^`RY%?^ z)Lc-&Z~(#Y8@&b$Gz?Hc;KHjTk3ykn8aQeq4nPcoA-*HUG>4c{D5g+G8d4}DMTz9G z``+9)Q!<5;bIzF!rFKE!v9|Y|NsC0-{JB99NBG8(Yb_PFA#?-1S3<)bUZ23 z$K$z-J{F41U|2;3EURRqaN9zY(xo`>l4w~~Rv{`&=;I;9 z5;YQ;1}wuSBp{5u(dKD3u*^bs(ZQs&3863-7RQuoc~;)0pzFHRMrr}ZX(P1&L-hK1 zl`urFk5>sJ^noFIeY{ExDlUsG3t>(d&T6HypwQurY+4d5rpgP$Y9NbXUGNZrz<~}G zCnqNkK)^sn1+RiA{6dq`r?jbrEGV&pVR2HHRmu{f|EpC;;mzi%^6GhXt%fnbbTO-f8A_#60ECLuLu^CtvfrYSGg1NDzlxiO=mDp;MYSq>eiStAwFvQd& zjVPR?m_(s?pJ=35!y``wh7?I9J?bw3`Tq@4x8YIRme^`it8MGOP2%bWH@uNrV$#=1 z+Y(z@yWacmZY%GVwn_=sDs7drR{3`Una^L^yz+-Es1b!ZU058DDb?~!&QL2#Z oAS22G!~c_zJcDYPm{P9n|3g3Kbm6R49U+;ArlZs0bUa)gs}t}KC;$Ke literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4869e00fbc61867ccab5b83187c3a146ecb36775 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/4869e00fbc61867ccab5b83187c3a146ecb36775 new file mode 100644 index 0000000000000000000000000000000000000000..8bcb89b90b81de30ef03a273aa6635dee769ecfb GIT binary patch literal 817 zcmV-11J3+3Fa|M)T>t?fQF^MwT)Iam`X$JrJSeq!GFaMZcB?xxGc#e!UwH-aQ}AUc zxL4o^ezOJU+Qgv&36iA;Rn8bUvXFD8w=QoEDE9Bua$Y z@l|5I%+iaaQ7VZmQe!5PsnU#7ZX;(Tnl@$&<~h#=6&N1lhS(vFssk+3raHiy1U;~F zVKJfP3uqRNN4b<{i?`mI>T37i6;r%5rPvtIZ-yGqiu=!hHo^x+SZCWN8YmbXP@%#> z!**AXZQKkqf&AeMZ@PON*NtmDKQ*>UYH=Uuw?XbEHO}@b4EK_z6#gWSp9C7Ipw<6d zqz@oqamIO#LW`Dsr0-t=W-;)8KuOGDP)CYHY?2wR5DvIktaM`sSrNucS?3FxdV@YJt1%YHir87Eomof5Jdd;L=I-}>_FmgrYA+R$To^JcnwE1um7X`| zT&6~1#uTzLo0Y~CdBQV1Rj$xd;{48*^Z%da+O$oZkRVxlUctj$$e} z;6VfT|NsBbFmMMb7$5)xL@+WSNT8iksZ5H&Ay5|uASg8g*89i5KCPK*{3&2D^klKt v8`n(h&NWxMv(|d=t+n1;7XX3(|Nme9-;zK9nyUbZ2POt?fQF^MwT)Iam`X$JrJSeq!GFaMZcB?xxGc#e!UwH-aQ}AUc zxL4o^ezOJUx&XQW$pGQ0a)p)>=XbW8|Nku4rfu4U1j*6^D*%Z25K9UXZ*qa+a>+!O z@dApoaTHybk;%m97*$rqWQ70|U*P9Xf5JER?%&O?#yYd!T5or|%8{t=qA>S%6jQ+g z4;r}t|Nno6fjdCK009^vf{_710_~JaWl{_dfx0LFL8%e2-ar2JY0XsQPXUXeCyTY- zxMo^+uDQ~kwbpxYt@Ylz00{j5|Nrv;mIMmWTm?8hFkt`^2si))2pKE{6D1M>&@7gV z&Yk|Gu_1h8y3>$#zL2Rm=)8cfe4aeN+-JV?YE5IvMuhO@2r+74rFHTPlee&1*BwVkE*QW438A)}&c zIprqt@PiG3B&~j0F}22CyVRk}>-`_UeQJFW#0Vs4$@AoKL0ajX9SiDb6S* zW=tU~B(qs*UZ9fMf{8rg*-C|Y!ZUMzRIbocws3xhbhdKjjKqv74B411m?u2Xk80C4 zZQ{^?1j*6^D;E(IB&b3kq?gz!CnCQ`nOvY)Z0726=eFq5eHllhX=Aovp7W%rh(JA| z4i?>4KlaT9)+FeGl?#j7#GwHRlBEY$v*ddOp11!^~ zI>4F)J+N|NF`?uOXcmn}xs+y$x89oSYWLn1Q@k~$*ci}nh8oU_`_F$i!UslJXWJ$k zC>R`2p~6AKc2|#W+zc~;{NW34x_cbgjcYtVHMU4i5WWEX literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/542e60846887c634378dd1b29d3ce29b90e13f99-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/542e60846887c634378dd1b29d3ce29b90e13f99-6 new file mode 100644 index 0000000..b4821c9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/542e60846887c634378dd1b29d3ce29b90e13f99-6 @@ -0,0 +1 @@ +eE_ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/54fbf0fc6ed4319b2c0986f26c3a142b194d9ca3-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/54fbf0fc6ed4319b2c0986f26c3a142b194d9ca3-4 new file mode 100644 index 0000000000000000000000000000000000000000..5e2b66dc6a3ef1c19f76994fa039c6d2338379c4 GIT binary patch literal 3 KcmZn`VgLXEumF|- literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5889a9b84fb69d2913d474a381ddceb217137d06-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5889a9b84fb69d2913d474a381ddceb217137d06-1 new file mode 100644 index 0000000000000000000000000000000000000000..d9fd093db0604dee471ddbb7927c638afa734597 GIT binary patch literal 100238 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5b85e7d11f14ff2864b2c56e03188f15e52fd9bb-8 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5b85e7d11f14ff2864b2c56e03188f15e52fd9bb-8 new file mode 100644 index 0000000..480a005 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/5b85e7d11f14ff2864b2c56e03188f15e52fd9bb-8 @@ -0,0 +1 @@ +eE@ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/649971daa4b93c4ffe6190415f22569030f2300a-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/649971daa4b93c4ffe6190415f22569030f2300a-3 new file mode 100644 index 0000000000000000000000000000000000000000..221b63d33bb04a61f16afc1e9310e273851433f3 GIT binary patch literal 34 qcmY$`CBv}q+ML*wxi#l3j;Ba7G)Sv3$T27|c;yLM9lc)Srw9PxGz-lD literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6903fccf79c27b4cffe21090d03c6879cbb72274-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6903fccf79c27b4cffe21090d03c6879cbb72274-6 new file mode 100644 index 0000000000000000000000000000000000000000..2059ec5edc967dc46ad6b71158d1bf957ef3c446 GIT binary patch literal 10 RcmdGG4gFd_g2uu{O0`w-|5Bme*a literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6a88ce804bf81bb01a233527595b27668cca331d-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6a88ce804bf81bb01a233527595b27668cca331d-1 new file mode 100644 index 0000000000000000000000000000000000000000..16904e3aee171ff701c668488d0e225baeabf662 GIT binary patch literal 131073 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�H z@a-WW=|!EFs9T$x|FI9q_I_fCi$yuhQxLk|nCOY+*l7-uoVd-bm5rz#YJ!HqK*Shy z-q&k|g!ndyg6QseNO5&z#uZ-%Lc4A8fP$m^|7EVBXT6szjW)abBr#9BEe%k&(|CL_ z!r;)6aWFU}C@aG^06Gis)W$`BWNX>%EA~Wxi`786I8^z4cAvd?kJDZ``$AH7fBgQo z-mXI!3MRX~d*oqbmTP{>qH^^&FCd+$_uwQKfgaQ=IqT)U5$b0%XlPvSu$AwULPBiL?M1vDXZ zRp=yXHsOzSzB*FPO%51-yS*bo@bFNiM{S>6<->g+_oweG0Mqp)&kb`d_U6Yb`%$W1Y9|Y*wE^zsF!K8zUndW^oI&9@ zeVCgLy-m-GD3XyRnH&jja+@T#xs*h>V}7=@$(!g%C2@als%aTXEds@N0%3F?7_8Z# z#6L}$CP1CT&yvEebG$L*=sfAsV=O}rz;-O2(bD|wZrcUlxf&dSvHzr!zSr_gQrBBK za!OrrXfpB=G!%hg081wk`rV&^73$`J2DeBbCFR}Xj=_b%_geM+B3N@rz2A2xC7P6U z4)K*!%}tO9gfA+E6dDc+Eiu>ECQs!)EzR8Wv06Yu&|J#^=P@?DJ*KvYWYfm}f8nEX zJBcrmU<>jVU9OS`w&I!OTkN0kOxYpI;Z+y_gt4w4E%36uA6ONPEWh6y#hM9Z7_;w} zVkqa5<9T>aiXLmveQyTtRBo*@yf*`fHJcIv75)EQ|Dg#6uEEF9@9?qd+f_A%Mg`&!qq^>UIeA#wGAoN~W!$^Tu%U46kXs`d8XK+L?FJn;*uXmsIiT8xwoQM`x9t z^C95NdR+i$ElysDk^t=}jgMF;YmGRbs*SrB(6WY%oR_z2p5~X`_2VytL_;$l7Z17l z1SGbpF#B%2T7Eyes2QV?K&hBkvBc~_?t%vlemqHYh69zqC#p5SbKQX3I8xT9=l7#t z6};OYF$pYOK6ZNJ(EZc zqCu|EaLrGCT;%@Rlf|mehq#6?YpM+ zwh02h3j&w#ZIcO_yqgaq4mZLtlhmK-+&+Ihe#FW(=aRTLU9h;rqHqO$K*KRGmM1V& zoXEzBcG;2BMln8h)jU*-2u9ni{dE1+<$QoG*1|cyYdPSgQSRWefu?j*mAo10`-7J# z9yw+P8-sdd3}A~*uPwJN8z`h&0JQ)d{p(4*r1s-Z$h`MB(?X3&5j`a@YtD4cR6zCh zPj^q}Tk27MjA1c4S;>W1F?`&-N09VoHK{~1+$?^s{rq+7dC}O#IvPc zdVfx}4EFnJBZPr2xebrGe4u4=cu_EMe;+X3{0bbwL;F!af%NqB2}F!v8)*M@zEmt^ zzunRanv-M8<90xw(+_}7R}OLT+O#NLlc~tF%IsFGI=S5X7+LkuarXKR=;8;-LF&(a zkX0T5IbN3OgRJ>05>MZxH*3P~vq2HI7DZQ;sj7d`!&?b2J0=)1X(X0qjgLGysM{FD z)nSs0H$N>6ii}fiVCHki>XC8AvuO@h!P{&t9pNCL7G?8{$Y6?+%LfbFNqzmA^X*d5I| zRoD|n{cLG?BRfQKxp33+p!QZDGJGVs|0&~~c8K+Ky&HrlaQPt-3&{Urm5cW4{+6F{t^KoB;hE#iFOS({nXAecpFx;uoFW$ZBP2Qm%bNR zU!FT-zIAA#?K=Uhtux2Ok$q_3R`j-MQSaOxqMCqaZ(jS3pOd9+=0X(Inz}9k5c_E`dH9n&!nkSUAS*K<4#CE@1kg*%P%xR% zJXEBjKdVTYWPTo37Y0XUy-yG{>2a3+n7D9#)A1b(WPYX+1LVPy=)XhEO=-@u3W)n3 zYsiy!E8n4x>0M`IcYeJSbIlZM@zcICo2U$=p;s3eK2Oz+i%_=JKD{kyopt@7=y1%0 z$PXL%pzGrkww2e(7~sukDJQ}gW^~R|Y8;ZR2#4Qb;$aovqHzPm+5d53u0V8u^g9P+g>DB5u?-zoBK zexH=wBmE?4X&+cP$iya6^r6T8V8$_g}yFt37 zr6i@hTe`a&q)WO{K%~37K}5QF{x>)?%b7K6&CGg#uOHozO?V!-uj@RIW8YWL&8wQ1 z*<@^(qYLY{&J6Qi%|eVO=M-d(r1w9~hQzKUX6G8S_YMSN^F25m+MB!)d z;?O`py&qpHP#Hp4A7Na3tAJS>u?mg^-#=-N#){O7<{+7ZB*bzLw&7L ztT;6}(Vp{SURw_h==3{nixl0WO-~#l?1zh-tBZ@9e*DJj8>N93+5wI?t+GSu`G&RT zxtEZSLU~U@hi-Nm0^>Buyx?FS{@($5*_wLikDB){pC3ssdGf+a9)q06rni>hZ;TbV z`4v+T}i-Wf&hebn=cAqfHWP<0CL6 zyFuVw?-q#KAV=yAl&^^WAR|#R(OKWhwd+AVddzD_tkVfWg$xGnJe&y$Mk_@O_JL%^ zj);&mVsA~&TrWGpxZ8wyls`e6?t3>U!43TFIT=RrJeSG{!a#a!a_wG>cF}8@g9e#d zpN`{%`QyM<7pex{JkOa=>pLkdY-Df3Vqg8HEXfYmIqJL0u@$UDg8+w%4kLo3eF|dk z!LT4p{p9+?R-%*h$q$8)IS43=0H(JE8uPxqHw7+;>{Oc0$1Y%EEK^TK-7$ z&C^}A5cbc8OV~2Gdlr}3tpY}GPe{o2BtYLzLeU(Qt1!%K_swA*S*Ji zm&VeWl*W!qnv}+^s<=OIot{)HOlO(mFlo8mzt)lMs}~umvDU8R$Dml0`C@vlB2mX9TbFBwIQR}sMTC6g@X;|f z@cT?VG!*%PO_A)uUb%DkA_NHzy@8cgS9nL>yT-gRQr$IG7PyLUjTMX?B7sm(2>GZ} z4bt7MXx(*jdNm0bH4VoKc7o_rCBC#w+60_ul@A2TN2cZ>q9LG?;NjBmzI!j-Ed&Pf z{uhS~&M)1(dxuN_Vnk9dnYL>EGBISnVnm9=qz9u$vp|4bS_5_4;#|XP4*EK7dPklD zuC1Z@>~gLE!fLK2CF{5d`X;CT9*^6xJ4?Jr5zmV@DI5ii48XN|PNH+}j zsS^^q3yg??p@M%p?Cr#&OpyMd@5UD~GE_ulI>TZVFnYhAkw3`X{W9`|RRj4>g+dSP zpTK%BNHV?n4ff5>1^{He|7mQpv6mnnm_5!!V%AZJ93u8`azr(l?mLn-^%BJ214tAw z+pGmQd8w385nsVzdkr{>e%W`vSPU_L(=Pb%8;U^iv0O04>?mGgAn=F*v(^z50{*NW z&9GD4mMb^jkPW})NiWPfu2QAG9>4~$!-BmMfNw7PzKfC=(NFe(f3WfD5b_7UFiHOJ zf7(I;e(7R7BE@8g1pC*!wFW4fL`O!#@&7Xg9hkU6fg;q~!w>9RVGs{VP6R4)un ze|#Dp09Fu2lgCWj(2`#jl%3%qo#AI#6XAZsDAti=#N z4_C2&$JJ3VXA4lJMw=1vK1k%(rh}#p)bYY7ook!40D%;5o?4{VW0=4n7ir1&*Ppzh%X2-NG>&?v>`FbIT%*Ly2I~xO zU&I{WMGV+(mdHO^0udw{g}vk6tA0IRXgg6iiw8bJ8jXRFL0u@pPKHwyxR(Y`hDvPC zM=a!XU!RU~dd_=aiD?KH%2Fkylk*aVK>$*ksSNTykkDb_bg>bi&K&3uOw!&i0mSbIznzro}}SGTr*MG=1i6f@8#o1)kc?`S;k$x;jswmR~pT|G}$ag9^IHsYoJntP62+xT%;vF#lYDYUlJJVWRi z5c14v2y=G(EINC4@U!0P=i9I%X@lH@E)Zq?x6AnY_u>=+JC_dLN~P1jFIu39g4ytS zOO@BDCIK$KFGLo`{xh@1d1a~p(sHxZU@S69cl9WxLYVBnP-1d-AJ9ghDiiV4>V}3! zU}ZrY@rDwHS*@d6l5t3^Wn3au`|NVo3e&0cHWlO{+L^`6_w9HF`qP(Y?Q`ik8^>m8 zM0vOG{Ah)L+NU^1q5LCaodEw|4T^*y^v4$0mNh|2muZFHCZ@HCjI#O3;;->vN4V~rT6x7SDE0h*kB>-oIu3h3&&1trY9-Jgt<)H zzK|;`%y!3~VL+2zu%S2IInR0j5bKr&HtyLYJo>+E`~G*X?t^ian3Qv#!B~xxKVjh; z`8*$$+r2Rr61p5=#oF_Fzv zcW|w4v|zx=w}0viLI6r2kFiiNoyfO1U%EU^zZ}F1iu5K!2L_vpM_HrIM|0Y^_<->z zbNCh$nHEXYG zacfUKj}sH7?>If;&W`pp0CG+Dvj6A`j1LTp5K7Jqnt&c@8jk=bWYaT`B(4buE594J z%${-If+%-zmr$o~o~{}UeM0t{s%FpWZ296g6hagXGZec3m*8c_56Q_S^pjU&zSW_5^+I#V3Pi|MS$U<*Y?R91_l~U z7*zm@Z4Y#J8MB)7{Ih(Qa}k@7J59Qhe(=sX`&LQKAct8R#eK5xzWFiD)-~>$l#j6y z(_>#A#(=A#eIQ&KyrCSBP-QTCjA);FXI4q3e|cM%z9 zB(_=To7ZIdS4vf$ztfPQKkk97A6^#D&lP))5roKKEX+E$5C<3bNZFkS%@>Do!{(7`EkpUa**@e-)qL(4$B7rZ?SuRmFKv zRbOO89rBYmvWw`KBC<4D2QEaY;Mc zjo-xPiP(^nVEe7NJUiW9NC%Yn9MALSj;rc+;^(CfCJFP;U6S-<6}5KqI4w)}7mvSj z*9|_VxB1=J{BPJ5AO_UUG>n8H1RomqxgEeTnszkw-)6tYuiIRBX)v;num*>QDHBD81eL}7^nIG=HNm*R^Er`9M z#=OPc(X}!mGSIAQcbzSn?0m#C$8Plm1>(PQ(kUBV=B1@OGd?0ZmO3zcTA@6hb;AGi zIb#(6VD;}W|0+@yQQ#s$npeuwAB>-s7f;?5``-0Tdsy%Hom}*R?AjOO(d$C>Ktz3orfr*2NRc7w=gV`HD6xPV$_umuEx zyeMVu^rCsSQ9*vnpgLQrt!4A!C)_o4GQ1%LeaS${EQPDNhQbv^+2;#)BsM%|pM_sV zG!;r**gCD0P0(**NT&3|1i^V!6TuEBaua$&k#jc5XISu1^2vO-t($b`*#zwvIfn52 zNkXv269c0Q7*Rj3Mw6Ds(y2`eGAz{JW*1(6@Amb0FRp-k&WBVWabvY2#@^KWB33^| z8J`e3cebERN_=+q3U+<|_#^K#kRwfK61oYd_1!E$W!A=3YhrGO-chazuQDK_|s{;SEO&)Ouo{ zC=L}f??JQBFFVaQ%?yI=ChQg%CeQo3-+4hSwUw1|e|t^WD$7z(gAyi{ z&qsLIR&;zNnc;4{IZWyf4XV-@e(rPz4{~<-)KhPly_CWXYs>X*NXmHSi%MaIhg#OY z9e0M^`QB|~FC*Bp_aABMADX3lp2df}Do*1%HdY_6EV`b4^07dP6Q9Cp6*NOx)Fvd{ zS0T*Rv(zBg^_gYMbI=6C<8-mgSd*9DLnUU-QzZN3If)<4|0RFDcRBN$XLilnlK`WD zvQGs1&E`UEa|`~!53t+Z7iB7b{>~uO3H}oKs()u!>udUF6TQ)|2V2cnt+hf-x!V&%V{psffbTmrP6T=X19vZ6{5I!tXy*QSqYLxa6F`Ju**d;T zYkliUP)g@#beUap<0f-%8lO*qK4V0EGyklo(nOsg7x_S608#>wf`1i}G_%aFos~Ro z##{>l3}BY;nzjy(K%SAUSpxFm$US=YtV#<(5HAvfxX-!6kdMcB#mM{3H}I$q`ZVcB zx2ITBN}In^4x7JevB^KUgQax)9Lq~j875vaVV~3N*}|T#RXE+Fuky8H2~t~|sIGKU zBGvg-ZiLJwbO0(bZU`J_F3j{WJGh=aiO)|Ab{#L-Z|)h%G+U{ARb{uer?$B<;m5hF zF+?jn2cX{P4JwOk%5=Lkt|tBa>s3yfnZM$_L$_$>>gyOVZ+1Yp4xju*AV#p$-cY}b2&Oh~M$6ewv<&8vy3wnQ}(Mpx#r zYGSsqjw}lVb_zy!1Yi(w`YDx^8yHFz zbl2(?o2R4v^t06_AP9CJr1i_heGE7Sh$C-m-|*E|y}hD3Clfo3Fcb-}mmA~JWnfRc zGnWpDZM!ShKo({e6JLxL&H=?M7PT!#-7QI$fa+%Mc5q+X!=s}E(t;lnOFeH`xM&oF z(C=P&?n#WwZ2_D_P52_Ns=K+FX8N@Al(*@^AURGC7!6&7Km<;`RmeT1&UZ-n*|hIg z)*aw*jpk>Rr4u=GyV9qn9D4*&Zb^a-Db258Xn6e%EJURYAcotsAf`N@@C9GI0P&&> zQjA?y6&e)7XZe8}?bBaTPoTHR+6T4+S}+tQP32ZQ?a9_X-(OL?1cf;o%4M9luv={u zRkyWsgu&(VRRK&dj0>W8_iJxM(3nW0U5%3!XwU7$r1cWw3T_tNd)KnG9A+1|PYyUQ zD-TSPPNHfK+sy>)(!%SuxH`MIdm+OBpIzYkKV&?X3&TkGnjss1Z|{8Mi;6o9Oi?rR zz+u6KBNH!2Qwk^TCe_Va8zwdPn;k_7XHcz!5r81kw2Eej;%;>&bjP6|BX6Dzp!U0$ zPTu4{puab8r#7mGBz}Q^7pWJJ<^U@p)h?DQ<4k#ZYXMOJbw&(V#6pJErQ|$8jXU+` zjHFWMgIocrZ=osHeMe1M^fxhcKCqld`~At+I*VdQF6v%YN`A@sRB1mE%_EGNQOC~< zOgJd`Aw(6lu5vX0gYZb^(?w5zQDJOMr}Zur0XzCha3TCoUT2D+iDZ7KM3R_|ptUMb zaJCm-Tnd!b@G`VQHz@h8(!)n_BN$1L1?WlpC0c#Y>eRyoGQ05{K#~dx7tMKJQQhJg z6%uT@vn_drIssGG3(Oi_nppuzJL&$Pkh#Izly+l#f^Y|;1=D#MxPxMBW@97CPgP}; zM(62h3PRCsB|oG@H?rn#yOAnlYHS+9g(_7~umUNodI8ja^ZCiQ;X833H4TZdpPlH` zHPw4D!U$BT6h~o%|6w65oC&X5As`SaPUipX}8K+664^s%>DxUYo6nQS4KS6d9|xa z&r0nju_OJm0%}-4WD%6sxa!d?*d6pPdhruQTC5Knht*`os+(~TVTVnsKEd7>dMD`% zgHKSv7h~!;bu;(kD-{YlC3Yk|=I-ztQ&Rg-rq%I!8?A>iW|1f7fM&uK@{y2S4%42GmyUnmrq#;gzp4uLMnt)!zPm?H%A z*bzSM0`y`>zN$}T{*#jOYX%wJ&$045gBD3tWh4Q zC(Ip;Y~4<@^#)OxX^HG>Y~7TT<@a-{<1zP2%IB(q+N=xK?J_`?=RH;LvCT%~6lY9O zDCsy=@tg3GtOWGD;85UA82G#X5!fqI*o)W{Peid2ge#BLx_2o!7uv$~D!9A_cM7la zmBzl7Tj_+0Y*8s&;pukkV*2sq+u}(y35t*NvA@G%$6YKlj-h(_qargUMrHzX4H0Nc zRzFlZaD8s?6e9f@qrx<`rG^h%XW{CV*xX-ezp$oJG-lf?)6oy%Cc|ds=k0vuiSS7u z77*+Lf6`Vf-6ulqFj8z|7TcM1bFPQFmq5_g-rK)H+1BP(@r)0^&Xq*LRecD9U}4a- z0)xOE!h4cz;L$gQaUiTlb#-gxc|5!2P;BKX{F<}xC2-wKmkg_U=^vbzE`DGNc+;Ay3=_7^*xAlhiqwnz=1!ifp)nqvzwa#gp96?_| zvwU~NVPdE2cfQ)zw5f*kH}PpbYWX2W*CC5PwwBghN1L4xj|q^AoaiUal87LnwM%kZ zXJmmzx%rJb5wQ;<*mpCXf@<#C-q{wxy7AdSWwOU5f=^@Tu3Z;RZvjP#fmoY$>gTqz z6^mza7*D=f;`nQSj75Lsx4{5514arKPCAnkoq{G|8qFD&#go?_ESU9$fsG6cpFi?E z!C$oozuWl;(S9(@Hhk=mFI%Yx?<%;H_KI=un2KWPtjzHZPacg(f%$Fl-5_L-b@G1G zM|$nCkgKzgR=mW-xZJ7jCQ3?H-Y~GF*cTskrrRz(R(#+bJ3g`IC9n`btO26|n^pv2 zKQj+qjS^XYkKIlz_1K%jikH1m)e}=M*m63b)7^7GQ0b^uy?(=bvdC%pPg39SQ5fYr zL`pdTFma>}X^ZTVHEDL|ZC+X8DBu-_LG`1n;D5k&if)eacZkT0{!BjNN{RQl`g&(x z?f5OcVEtDhbJG*xxo>i4dyf@1Poh$s3Hvbc0`n0ylzy0C7NV&VT7jXU`NtJ6)cXhz zKYz}uPk5w7XqrqcG=#h)O&UPIhwvkG`gmHKHU&Sye|)wfG)X_yoa z1jVd(w2yAjVBURPrsOl?&DoQ6VQsNT!M?ohk>F(id@lfq29)&L&K`L1vYOXZr2qEX zQ;>^K6AN_SD<7Nh+vcdhCLzKu>;y0+n+t(n&DI73>F?IJ|EN#4BDp_4ol@(PunMr` z0k1RL!FNAe#f-bR;@QHHgXS-2f|qfA6+Hh6Har}7VaZuoa5>JO6+TlRRC*Ud9U|7E{_$~&_~-K!vk$`k`W%`3!G+0W z<+TDHUncZvWOSG|4h`#7NMV7auwG3Iwizr1`Df87!aH0JLhVzC7Es3d$gb0?*B4KN zbCRoRZz(Qs-G=CHlj*K*`OJ-dJR+_@m;16Gh9oj>dNgf4LyYQ3u*;$8skIUK&9T&T z#v7kL?fw)5^LU815^E@ED=o^XA_@%%@4<&4JqkqyLXnie%S0NDjml;$w3(j`E*wIE z{pI-)_~DR%MMZ$-CI;((MR|-XG;^cEtZT<`xTbhL$?xBAgz2(I^{(*gJL>0H*&iqr zmv8y4R@1r_WqdKO`(AC2SR?^V#7mGo#hmuw$7BNdjI$+~+M2h#9*-7x+sCapPF|U2 zcX#hvf@Id7?(8fWBu`hp%Gk&NU9?kj5*3GB zi#I1r6e{g#;J=UY-U4$x&Jg5BhS)&hE-Tx|&o?qS7y#k__Evg0f%RXcnlG?Y?` z{Ce;zPP>1ru}{4f@Lq@b$4P87X_}2}o9g+KQM1$551S$9&Gzb&&(jubW4{F-jN8iu z3BM*sH^QAg{gx~o4_ao7QPt@XfWaWVk7}oRuX_7oVDUrY{sUBIrY@Nu)Kvk+LCTs( z#OA2Hg-TGO63MNj$p8(AXA{eRuIj{+8| z!f{u01b3F9nhPd?j{o^m`JCjTAf@xraN>tpB?U)CjsC^+#Ql}&BGU_E-6HjatLsD? zbl2l7QpdI2g}LIpXVme5_<_e@*`4PT`)RG?K{nZ|xpX~DpE%g0|1yaAFQu7}PMRce ziUS;uc%m%E6;amrmq`SSBsdnUi%9Eip@7IpLq<=k(ezHn{sD0l`!m9NH_e+8${tX# z@XqT_Xuz4t^i#PDIOrjflNFW{9vlv1`+JVi2na$DlY`p5x5KkU6XrmmlC{m=BIu-c z-@UdlA`t`bv@4+ixlXTY2ORfU)1buy&bPdFV=QD=^^s8|&?ys~k;Yb89a7mNUO&Y- zbs;1I;o*gW-J>uZF6OCogSOw;ob<3k(Qi+rcLm78}XnH@Tu&--g*b)Wt;o?#)E~LB0bA~7Bi$$(EjMZ|xFB-N|qE09D6Tl=; zL0nZyGJ+Z;wVVk7OlsV9-v!7OZPMpYx}0w!X(Re%o^E~(r0_z^s<>V15{1Np6Tj2{ z^0hllK<)nq;A0``|Jv9qAOu`SH4@C*!0Z1XNdXT$syHj*)!ogGg22>bl~J!bKkCyx z6eru0vnwTyiIts7YKw8swkn z3;Os>b2}8+cl%UzPjd?bl%w8xXzI^iQjYaqa`za6=Eq-;$p&b->TkO*%Shf0$`*RI zaHlBr@CEICEP0+c+p{BfHD=3HP@yRE&G;s6lHfo)ZfhpnJ@FIxsRtQ8PQ1`~9SFO?_xg_$YKoKYEe0ZLwIbTFZ!7KsI zBtpvWv_2)-k1qh{oBF<<_77Vum;iBSD3pcUeU#D<-G0oaMWcKmM)Z5??3~@ySLx?- zOu#o8!Mfc( zG~I-Qjg!IUU9J}B1%) zI-f(s!G84Ta<3dXD9t~ci6Y+<#mhT^OK1&-ti~RtqZ6&-l97)4u`+_IuD@+ar^(ANIMq9viU2(9pJ9y)u4;TlFP zix>~tY)@(eKHpLXXkq_kqgtoYqT^=VS541rvGg@c1B}vMxw0v&h8(1QST(UtqvUmq ztmydYj%~@pJ$ljeJjMvCbKwkAV(uA_=Y$w2-LXUjcR)A&!kwU0z&GrNzvgMW&Debl z6`#Qhd%-w;^Co}A0%GS>w$|PxMzop-OZ%=UXCRnvNJjGTNv|b$TmHS;L& z{FTC238@%pvMdHfB_ z?Q?Ojw~=owM9CXwxp}0?C?7W~oa&V#Hc3YCT-sSU7|WqG5DTvRkOS*&@(CeN*@QOl z*ly)V2@p;?y65xBd8VQI0`;HDlqomPQ|_GMGjhZ@RG!^E137&$8rh?8;U7v$sZlq# z^z(s^`XxAL0FE@oiYz)1D75ogB^rqC`}IEcH_o&IgM^Mk#~~s=5;9?g6aYtnMTe4k z?(I%0>8{R*FO8`|iMdq&1(H9JSgg~kz%*smsm=p~G z7Cci>X%~?hDExy7`Thd2BPPC#ps9Wm0P{uwB7;OeV3Z9xB9eKI1?qUG>Ejqz5g%T^ zp%&I~dT(o3tFlG)U>m1dYFoNLkNTIy(WMN3oqqumlF`sMx@ zz5@>}0V6a4Pjg#iA4N+O(-JZ1AP24fh5OA1S&?GhXT`# zyL8}eG1w>o{&6$^my6e9e3P&Khly2c}NiHs^PD>B4T!wa-zn?I>vcnQNm z77l^qazloq0QCUCBG1C$(T||aW$5>MO$xXia`bjoiCRcvGGH$t7pyJv9lV$-+DkNX zmu=iJ-2}~op93M>Uv2=Xu(-yH^*fg|58d2w*?7m{10$)mW~-{o zcRO+=Zc|^AK)xr=HF*ZWj-_Y^d^D-gx%PY>@*2i2>~J?!^#- z{dQ=iKjK{AFepR}f-*Zjsh0Y(CsgryJYW>WxCcbS!cT@^Q~L5+XUSj4=nX!28= zl@sR5Z10ZT`$G1ac2})VC|f@7qF?6Gy)-6mb^!E`T2G?IUb9`Pp?*P z*i)S&D*-pDGWYhMWG#xDrq&Q%hk$77mgq6=!Uh*8Lf$GiLoJ+7Ty$*jXeVTr* z=l_pmPbx4{UNf$;b-3b(Mw^G^V>wYT5LJ0uufoc%pq;lo(* zSLplT3(H{Aj%HaJa|yK6Ia39wj!Kz!jHHzMhXa3r?Ep5WIK7wGvvlmOW_g{(6?oXAGp5w(>ye3`HLcT#r7lX%*=U=xS7x z*OQMHdB;|yitq$v;C1qHVjw7dRf?)geXY~TCN&bt)E_^8Ysn3I1AB!}=yc9MWx|eBA-HF*(|GgVH zLd%p`q!J|$^vk+fNLRohMIo>pM2!w_4%=y${8@)Bw{mSt63cFa5Cr z^%SB??OPe=GbC~);eVPA!lOU3%HxogID6ZAZt8ZP7q3$8GHwxKwEm+w3lym31^&_W za}$Viq7kz=pe=o9ikp}NF)Z{PO>pc|l;5UU;_YBKUNzT7c}4!n_v8Qf0WvU#7IoA; zthxu2;QxkF_Ck`1ogV&!@s5e5#}AU=F@P#-|EX?t>J5Qu00)0L)Ukq}5k|1&1JPR) zI{g2kAL!ZuKRO=wSF*w`(0$MvTnevLHAdI-4kW!_|{DyMN_F2B{Hl4y`pAQ%>J*C#enWRSPGk2S995PhA)oo z#c73Kg|%+h7uIjjkf1%UJlhtG`CSH7bCbG%D(ya=Kzi|5gm@Vu@ZBchMJMe~_8m_% zCx_GFUs>*!FP_)#dlhyUQegO$Dst-R!w%@=qZ`@ zZG&xY=C#l$jbT476DLYLLPRDZcLLKVF&QRN9wF`o;`rE)(TZx(B)S^arMFVgwbd&J zafjg0HSORI+ri&4U}c#;iBc*lp0FEqKFGt`3q2fR$Efa3! z%Qt%lVo~1?`0@nh+A?9%GS3!ei)^4}&!3$x1BV1!m4*1Hwy;Q#K%qEinCZL6VWg-P z5YBeShN%OJ$%sMgqmc?>>;Q`H$h(X65%*16h62dNnKdum6MZT`?X_f0#8|{h!IpuH zZb9n&$i>rAuEiF~JfkvDs!>vjA@bUA^W2@H2i!y0I|POJpJTUVF&>11tfYRz0Mz4? zAekWSypvwS27Xr(r~B0?yqbt)64m9{Wihbk1PBSp#5zBD-@w-Z@f$gO;e5+`h8Nvd zr6DGc*TnWJ=MYFQD|W4;Q=-r@2^Ya(pJaKCs=nuNcw-?8ZpqWiDK?QUt$pxTelKIa z$F??X(>}_?_MX@pMccR zCS1p2`6h*+@3Ak`U+FCyHOv4`Jg}9 z{$rEZ2l7wQwixiK+x*!A>8w+shyAvzYLi@Kxcc8?uXs`M8D&85 za!W}YiRSpQJBh{G1w)rN4I+7CyYbUsK^M%Plx`FPOI&Vhd>6fpJ6y@FODO8pT~Jlk zP*Cp~UZo3K-h5)P??TU6d3^KUiiNP@8jXztV*<=esHk=eE8;_`Kzbd_b1$!G& zdAmBBuydFIIm)b7LS`TUUZZRrrm$C5l9*~l0Q}SCYt_6ovjD9ciz(Z24qD24A0O~( z{JR2>Nih9%;Jm2**eg+&3wE5uuzXp(rDj(5iY9Ni`eZSv#mqi;Tv<4a`n>u*O3AvI zyt3lK$$+}{c!Fe9fqZHmX5W11zbemOoj_Av(wvEmUVOaRAmfzqqP(D}Y>ChL%0taQ z`S5+Xy8rBZ_pd1iw+{USI@^3{_TXwv*nM@UZ#LefE^I$<8M=G@{osmHS2Nm>45^Jh zJ8E2>#Jc`D)W3#uICf7X9-+GB-X>^AxfHuDi9r|iVj+5`Tup(JAGKVu5qS1j?=fU% zIB<_R_0WN>`rKPJ%ceOre~7}cuI1?zt@ySKN_oFc)r1hG?}}N=Txa*z^R_n8gT^Qn zWlLnakH5E?;eEM*8#YtHVWq66=JyE>Mz{~MMOZrBWLiZ#pLG1WNoV9! zHCj>9oU8W{EC#f)Qi%%K#FGL@OkucokpeKs+Z(cFy!qSt3viFbQk zAzR?dnzdbS9@pS2IE%4!Ts@#>=6c&HI#0?N8yh!TPFUKH40)T6&1^?BvJ1Gd#A!3F z7&P2b>%jo=fGtUs=0*vrtL~- z4PEAf44cffm#XS_68p!4$GnV}wPXsnb+gvjj0JJ8!rO9Ajrsz*Cv55x?o64}625kF zTaIp9YL%yM2E4^6Ki-RIK~}^>)IS&+ApwVe2Oly5_~e9OXuh-99{WKdBH$?{;+)t_ z@yA=1aZYeAaUT*9z^c=o9pBi9$)+#GM|h@ebSdn0>3Q~BOHsZFk6C)pCw%;|e~2_H z`wa{!I`2&!3VMkPU;a&7NL6dN`|OnY9xGX6_#H*4BhvmFf!0<&Xt^a~4Ai-@(*|LdzdW7GeUg&VQ&`Zf=zC#S$lrnvN? zRqjGt`Ot{~WpT3f&DJ@nVS~?6U)wNNdKW?Zq#R+X)#Ls1LS1&`kQ#IMyCstbQr*#G z^L2SR3Z!~_br6@uHK@%lVXv;`Sh*w)=;V2O!Q!#}F2W%y^bri66c3sFe3&Iq>Dx|t z@+bPIvX?E_(LF*yhxst` zgoR*kP-}gilAr&5pd5Ro7lQoj`d(pjd=IXq#`(21wZjj7j;nnR8Z`QeJrc>Y_`*Y# z&KuTANRQR@0v1jp+7hcF(B-_W9?O%9I|jeQ;0msPhl?c3nZf(L`fSrsA}gLdYK0~) zB?=yM!CzRfv!0$PiO#_rJi0>^p!Zw3I;t_w8?vHpSESV%+@<{n=>QM@9`TTEq(#DF&j_eMT^Y8CaNJgMBVWBBe9-{P*q+kUOR~uEY_FKXi1LE+KZJwu0iW1=Jx~iTsTEI? zW~(xnHmdSL9n+STBADa)XqrRPc9F%>I%IXx)r_4exqD3r!vs-PQ?cY*ZidTrr!1=8 zM{qoFw`qn-FS{(c0AwLCakg$5sxJ`U)OoS2{G?u~Dadqoa4V4}xy^Mhwq}~8rOZaa zSZDF)Lx8 zhQdrcsp#dR^o3o$P^qbMz(Dy+NOD%5re&&I0T*L%wCoCxG`~i+q~wUMg=m?d$Mm&a z#xnuQ@P@)ebsmP7wmBg0{UTp=|4IS|#OyFJplYt8GqM7LI_|T$VgP7NbC_$>Xb8CC z%LPQw36eCrpwRIBfViUGKO_Q4q{*OFbd9a1vLWH?gg&{*&5{8OF$J!1&D?cmI zFq_w9VzOBg612 zP|)9xTcW|iqY>xl->bXu?9r&6JAHjPFRwIAqRq{}s>6YiIg%yVx7x1nh5b1suf5m@ zPUgl3{4bG8oBxR5*DkHjtg^Rlhw1u%wtl;lMY*H&+=H5eHP&h z1U16fkQLWx*ccaMzs-O4$rcjd?Hh=eNi%Zh+zC=uER@qonZoyz`PSFAjh##C8)Y_WeoO6%h}{@tnZ;6s!riebd9%{+@V}BGIoA?41dOsLrzLg zj4bZfP9JSIPIdE?utHk)dX(|H<#jc$!|}_b_L(iM>Uq8oGubLqDm*rAWwVOKG5FJy z&E!N3##I`9E!`0lWq=rxD#`ELY|VCgUwwV14vC_;q^U0rqlk;TEAZC&GK#SWZ{H^Y zEG&`(p<&Tc@eJ5c*4|`Sc!B%E2BRP|#OjIun|_Dbt-bW>m`5x&+xFSpe0hvF`{~8^-^>f9Hj!6_vthrVkieZUdf4G zUCicZdJN6fjrm8I5iuEFXp^>xT3lFV{OVR=E4_l{W z{W0^+4w#lh6N+ZRE8BD^B?CEuT!Dwq_FF%G;!bcpDt^26C|G(T9KPb-!!}a+s{~Xp z3@j3dg}GVvf`unSWNX3!V1mCV?Ee0vBLSb&uOH7f=4w57J{Y~~a!|rD<+2m1V@y8G z51b8g$2ch*{_SyGr5FuO;brnH5L9&!$><(6@XZYMFjIY`bI94T&>A5diW${FEG39pgSx-RK zZ%tMMkSH0%sk#4|zz?6hVtD262>kXSZ@^T!>vaSI5D^%3xQ{(!+dkpG;O+Tl5Up`V zmXZJGt!!IibUe$yW%HxQfBWD1+L=dl&~O8?7p%%WhFPu5+=rkDP;g!ZC&~olE5;cC zf*$+>V;zS64;STMxachx*qLC?vo2qHy1Dl{O!ZT`9R6tmyM1r{>utEu;R!RfFcYf$ zxt~0>B&{qjLY{COc~H^&XmpR9gfD=@$G){`x9RZIZXjl}1qdn!!@aCoVZZgvLMG>k zAlkTfRkT2{?6aOfcw0yHcwBz_jhi<`)<-DGuhE0xiCBQ~ zDigcI1>s`blyo&Id;{@i`;4ov&O?Vd&=<~P5_Ee^)y4ceGAH<0$#U>YfxEC9bF9#M zP|YmOc9QcY;97z@uG01Od-PY`@aJ?4^mI4&SDZ#Yb0f5c5`29AL<1bL`LwbzslQ#6 zy~@%yctpSpxtW+*A_V@q78V~>r{X~(_`@LxMg0ugKikdG=HvId_m$%mU2FJ?ImSG} zwqsDA;eW0m!*{d;)#Na6dU1ZB^auBQ_n$wFf){VLiWq?izWVwQC7p~Nu{8}R8yVg` zZtp!m*?;nx5f9@^Xu8-c^u0vuMHw1TNZAl4`8faSSm@s<_%INU9^o9A)p_#%yY*B6 z9v%l9WO)Sw0Tmvy7-yAA1nhf}AH=We*ndrDH-9H7^Xr0whnRl*psW)8vZlWUUTfTz zx(n@S^=$>Ye;>!{s@Mvo!kDpYxovA-rNDvJijGvlC z4q{D>C-S6k0L~u*kDJ`e2da#1DA3@*#2o75sl>cVV@}Ry0o}7`GWbg3^-o-EMoo@H zU${g(m>_{L>`#ebG8r6^*mgWs1Jz7ie!*V@r=mWd%v)_qb}^Ag((_j+zU#gZqFx%IHNk&>34FqU+_4wx z$ZK{~b8cdUiD&Q09G`;0-jr`Vp{KJmzL8I`{i-2Yfo6AG}SMQ_h zoKbBXe4orxC=~#~`Q?q03~O3E{5Wq?OO25Ph!679u`rn4N=6>#eMr}~h)*_@HWC(s z;*j`x(-8ZY^BV(!>dDzjyeO~XhdA}Y-|9yC^aQ=;@aGm{RZt_qs75+1gmuaHm%%w3S?@QvvK)vavARa=t z^XO$p>A`DSeNravp#5^%w zoPs!*;wn^6r<6QCks8zwpDLv8m0(T1g#&k1 z+&7nI?BXCTJpEScxNz=bJJ>`Oro;8(EdP|g^@)g&<9%^!^tX*AQV&K__3Saru2TL7 zfW>XH^}%x?-laghqy@3bp?H*R@*c{)Gd~|@l?Q;sRSp#Hku}-k-#6VKHlGhEhh$8V zUm)EUDx5WJ#g01zFBBzdN|k@DuxLVI{XOTdYB{&a3^pcwCml{eT8U!F#{&GhlGX3j z#1p*sZv;mtC;5oC(uvMYF56xFe1qxC%`jc`H2b)BDS&V zgCVp3(%A!D_Yf%03k}Y@WT5Q+$6T6MyZ@i`-RZ&KU7OnxpKdvxc34AOh-xXB#xS;b zwEQ15(}nx8y(xH`&xe_(&Ozup)bgyVBlGE-O&;i5qrQs zWC=>}gYCa@CO*1xiXDj%OXzE3mRG(zG(NE&En|{)eM1Wd#=#-&kQB7J0P@aCNAUCZ zl(sa?o-Xkf8o`?QO0@Cj>eB(Yh7FpRS3l#Y0>o^&ta?jROc9i3?d>>S3)AgLaIhN^ z!EO-%m$FLI4nMcmH~0D4$_}uZ1i}WZ`4*a(+<`pDO8;GO3XUQ5I|U%!2dRuyAsB^Q z%mPQ_p@gNI3@W%qEMZ;tT*_$Fiu{KcvOs1&-dFPR-NZ@?EAJ6nkAe6EJYH7k_!0lbRg}ZPkEJnFLh84^R|9& zOp1vlfuw50tXd3|T-C~h&0tz9raHXgqCo!m+zq0xUvAdGpG2?c3dB1A-IK#Z(dL(3 z*AM-Q$VU(bedmSesw%q*7a8i(>%Byl+ft(R!EnC!k`o2r3r{Z=C@6_I*;}yFD>Rco zF3^ar^#}hA_&r#t$qz(78hCs^($TPJZHE4?N(qA^WehCZFD(0qkVY}M3!1#tk54!$ zaVQA%GCZ`7zHslIn=%rw8pj4oJs9$cA4@r!H+<0?Kb`#LA&ZR0gbS+ubAf2119ISs zg!*9nVIux;L3#1StK@a)_;(@cqbnD>k#x7uKthsTLBZ&CdzO~P!+T*rRH@y6k&%4g zAYg&~1D*$=A<8gr636q3oVntnjii%1=O4J)yXG<3XQkwG(SI#Rw(gVti*V%1%br1B z6fWrd91@p-V!V&nwt=TVaAhnoNCtv{OYesy1BaFfLI`4~oz2^IyU&%8ZtC`nha2rl z*jnkNdR%JnarV^n(L~3v^@L>-w$q_UoocCyz3asM`te~MqT*M^4v#L|%b)$8mp2@< zJ|4PIC@6|KAF$+87X<*dnw`DRmPKurnJIb25dY#r8-$qs?~MKCv5U z3XF)1Rtd`M#-$>o`au}Oy}yb6QzSgO;@EuW8@+jUfyuz1Vnl@8NWyK$ulL% zAV88p%F(c;Oz%^;jM^e3LJvzTy|n}|u4qw!N)sKwZM>;&w7YhiVJ9I)7H9X4W%=0R zk0nU<(fU%((fuV&>qz}6`=Je+k|&O!V4=-m%^6eO_ZnZAFC;6G6LX7q7y>Sr(7lnD z%Hyt~ce2M{Oq5Clh(X+ApV58c5lNUSuyOBwyuU>mPlc5ze6rh~z}q?LE&2A zbFeVDXSkvDlI_!}yF9-NNg~QlCDH>_DkvQVE{Me>5~>LIgH=?$P{R{9I*=ZQP;I@UH8(vu`D$wBWb7{_bxIw%<}ZTT~Fqi+KHL%~=o>bj;rm`jrjbe%YZtFbz+Lc$;s;bxX*eP;5*>JS|Z@#`f;L z1Mk^Pn6xU2bNHajWsbi#$xn(mNEB+Qi-pBje-uor`^TlF4Qj|wgqSB}pL5{8bdDpv z{J}wI3ti;l<6l_L5Aey*F_$udkRJgEP)9{5*hJ|v5)BHz-eW&CNuhPtY|P^QFsQqK zdh)yx_iEBF0l^nWLY@qj+3CVl-wZ-pXh6uY-eX|F`(?bg@n_Xd*Q21lYMtTQ)Dsuv zs(c=fglt6njhet;QhNEhsrF-GIh4jyxDU|9oFpa1{UFdJ$*k-`l^9>Ay>RBYWJMfBlrgKAY=PD*--Z*ydBN zE#>tN3|bJ-3Fme|8vq%HgOOcF(gN1j=><*SQw&VwoY)n<)>{y`ar$Ulzraowvt z)I~^}@L+^vjkB{77)l9X|ESml4vF_Om7Wc6XaXwiL+C>xPdGUrh_Iq2@eXl0Ow3w( zo+-nyPuLEqnEQ0-h{%*&5sWV2hvWGmYhj3gVxu8oWmnKI;q#lj2-4pQChvLXM`ziM z?Iehv;*@t7GmN+YM8IiaVBkOXU`0iJyaN${k~xa+{_}6b==NbdL_9^GVIhbHRtVi> z97Amg*B6CbyZ}3j-2ZAvp(0r6mOT9OZpkh4Dg9S;dAW130)yB0N^b=G3@9ULs4&EP znah8jRs7z*eAQJpv7zU6m=e{0-Gi~*?FhxMqTy|b=b{;~G;8!aDo_Q4UZmi z08jvgGys<4FB%V>?7j0V>L3mhkloqyi;KoL0WDKOvCE{lH?ifU0p1HhSWw%dQOso9- z+)xFF=wIWY6Rk2teKZ3Q@Ib;3sh?>*%=x6GWj>mNi&S4O2k#*QzU^vbI1g9-BvO%A zn!9_I9lsSn>{=3C1#~B=&-t=y=A=sGH+4B!oUdqlWnt;M&@pYYpaT9`FIgD+11J(M z67gl24n)?K!5bovZORK^$0Hb*`nH-IO}q1h&Q>g5@J(TnEq`#s-PNJ14Uk{_p*f(K z1bIRDLUV{k#v-`Q`+{f>U(hW;A|g@c50GI5MF^YA@xe!fcO_KQa!P9#VhEJEMkU)b zzrXz0uA3NGHGtP$y9{9gFCfza5`_@0Kf)ptO^ZGtWQiXqiO<&e!USA<;budc=C_P^ zRuPbf-mL+c^AG!(C>Mjw!CHSAc~d&tICr*nhI7x3-Q~ajs_EmW`B(b0LUelj(RyXO z5OcZf(Z}zo9^ATLV`>yUerE=TrRc5uVm8Y0Bc}yWLQzS$fJt2kG+K=3!YVj{^OcPz z*kiA4F>?^FbH3b;d7k&(?w#wTS-^E`I4TR(ZE1$aJcA;QJ;uhh)VWU@ExC5d@R9Um ztltUcp3T53r@M>~h7EiQc6MWVuazq{E9$em2S~X%tusZ{o*Vba&06Qw-6ya-4ZM+Y z?_Cg9H!a8g?UE%@VSVXrmY0ItrD!rtP=`-wV@*ot?#^bCZYoLTh3a(k_vHX*#3T$Y z51&&7ju{V2}WxrtnVwxjz^ ze{K%%RXia$@7tYHZ!1$sAtm-g!H9rI%3qLB&W}>?<2T0|oMeB?A zN?*i_5(6^|_2V1ry@cPi$f!KW&tr`NRd^GtmF;Nxd4+dvc3alNeN#-vNK!ti>T2cs`d+XE zo*LgNbCAdipKRXnXl|dt5YV6Uh!H1212xj)qnbi-;^Y#smlMx`zSk>Uf<3*r?^?T~tcl8@Kj zgmmn3-{|qr)c>g?mM{X_LTy_}WLcBCYKi->p6v)3KyJvTfSOvMi2X^%rUv{SK8@`K z<=Dv}la#ZoGKuo$*k(kK~ysurAcztaAz%7)A4ix4`mzYY}ac~ugnCDaih`h zH|$UM-h(AJ+crJm|0AZ=bWK1=4|1?$+4Dz5BB2ICw66jMnq)w_J8BFV=f;d_Jp^Kn zLW-GU3EGzLM%i5{`chQR+`XZIVlr}#EUQ4RSszUHQ!JE*wKF70h-S~G0AznZ5S$SJ z-~mtwguvymOkWgWuF_550~E*VhUq23!GnUl_}5R#Fl%K6vlA756qGl1B-}oqCfslh zp3Q5WpC*9w(q|t-VHi_cElWs(;80-D6*!B>>rSWm%&0IS{lfMHQCxjVVve;-)vi@> z_U9+247qNH-xZd>3ox4F-0al3x%oC$`k{FFgM5zQOKSec_>T;3DudOF7`S-sN~Sj$Jn^+ z9*P{+?~S6}&U1`Hwv74z8>+RtIST%KA z{c1;)EdXcp;YIwcw|jGi{6+sTr9ejx*6myhcfz!_hp`BfdX==_=~qO{yyeU6I^F$o z*>Fhjus;J>?IQHP0P+^=!-^y#@I%ZTk9+<1|0Pbf00LrVg?;iRO_C!R-rt1*9q#T) zLt>CY1uCkzx=MvdO#CKR?{S;E@;TwZQ-aY}Vh9s(*pB#3UU2YpSX(*Z(l@ZG@l!aV@0lYBY(o!%9N`1FkBZ zKO~8sOotTm_(x9%-r21-&krZlI%-2e*S+zsd}Ee z5mTVSjqR7j4<+U0omM){ZHiOTg<v^$c6qpKRrO1Y(Pbrf!PJxpBe5ab@LvNAPqjviBN=rshR zV9`=(D2QdKFDI=RW6O6p@Os0*@mYD2%RCR;P93Y@F_agn9F1! z=UR=ief%l!*w0IFm&)F1Y2<$lb43zuPQROf^Hk^GR%AebbXyVe34Kq`D7>w)dN=Iz z+E04u##SXdytBpD9o#=s&a155Qu;BVp20vOkCbj##QDXrw{>Zm0m<5NNZ?9xibK!X zOsEEXgb?`Cikt1s{-6#|PcH*TG($F+v6y?cv9sQrshZPGJ*h0hNKd#U2$lG!0GT|- zPwSB;cqAwWkrAE420TNieeEY5?5<?%%Tuk0cu;ZeAVwdWtR_|1NF*7&_et>hF*3lG>aU8Nyk%i>LR|~0cqv& zjPNP(lSt=PTq$trvDD4>^kH??cG@QHtz(1tI(Yti`{DU~by=h*!uJB!B3ED&@o_BJbxoboM;rc*?c-iQ$ZaW7YX+_y=J~bypoARk`iEJPk8D^b+5tRhM}^pSqk2!u|Bkxb{>-$ zCkV45>GP#*rEoJXmWRc~1A}$J?=GDT$eAI~gSePMdd&GCFRR*FK6c{AXn6RUWDlCq zMY4QgY+kAnQ(<*G7#MSBU4x$-BUIIu+{FhR@t=6Ve3(~=yW%Zf;R!G0-66G{y-0CO zLTs_Fv37QqUL9SWfItT~UEKRf_Da}t-=8TH+7FRjj2%5gG!TxAfi+(Ucz8evSf~tK zWf?*~Ezr;sVnVDbp&HqNFPueUNfVK*Jy%)^_R26{Lr>{$Gt3Pa&C)`Wzvi>TMrDT4 z`#*u^Hdh|FNp5(Z_qF?>W0*n_JYp0P6ES^DM93i-L8kwG)=lS`x#;5$BI01RwHv|} zPq3lBYZvr*FGMfnfdXegme)LdSMkntTtmQ~bhN+Qs_3>%5-)f2*%Uqh_2z@wQ%lyO z>y1tFm;?p>lXJUELReUMD1chaC~+<9mQ_*iuC{HiFD45fmhSYZ6Q-UN-|qmI!&8t* zj?T2lYH2sP+V&FGPkWPT6c@ip9qm(iDg(XZ1(%^LN11w!G(0pr^W{=-H#<7DbW(I& zai1D?YEwepa>(?kY<-6J7NLrNk!kIiJ?OK;^>t^$U1NRf49@immwgM)zb4*LDkSTT zQe^wI!~X$9Kx4|&Lydz6XmHIdwHO?k7-Yg&bhZtqW(6cuN8Qkc^*oj0UrMj1j5_3f zdQgnho+2A$(D#MUA$%x>vsZg2tLA);pf4cz@M1tr3kGK#yO4J?kEH4VONL2FZGY<# z3ps))nz^N^D6f|Jd7IMb&AI3XNG}1h*{;k%0&`J-vS9<@D~iiG9!>e9WV;Cc6p%kK zVJ{!%V?Z)HQkM>lXp(zX-s{pQQ(COjUwByTEJ0N;GjmaPze~bGlEekJ1#~ijKmo%G z9xvJ&v-Nw0rkaQ4;8(`>Y}m+P@uv&!`!!wFx9?iWHG*I`Z0~Z3%mLUZ9|D!J5;;}n zmwS6bzfb4Y5MD|%cK`qj{gjph2?o@k0oA`)z$_jVCP*;z67fxz?j~7!fKF+H3;H_Cl<#NCe+FHDD)}ir{h?~&oyj^Bm zlle2`=_t#J{KfSxC=HE}ZJH%}q25&Gq-+0@U2PAZ< z4(J&-H;K1HPy+=D6_tNvpF~3JhDHCo8zH3Nbwvg3diu~efFY8PlE<+4aR*x#6J`(_ z@~(@cECr>KL7$=;eMp*%%YAyH|ALS6O$DOFeCOo6<@RN(>`26btMOuR}*C zlDc>>U8749cJc;-gJtQlM`w;2{B2r`xSYYmgw|tLYk^l*C0~mzy}DrY_yP!?A1eX^ z$wpKg_gn#+_V+7`+)pq21yGa0@Ie)wL5Q)}oQE{Kx1<@vdnb9ZAu?cmp<>(p!Q&Lln^&I(tZ?VQ6C$QfFst zQ)u~9PjTP%@iR!|a)WKvD~C2YpjD zZzPndo0KHDat$Q(K25XqJi>xT%;_R1g$myTl(%rhG3A(vnQng&u_? z(j1i4U1UJ~?h2P!5lRV&E%Z)3lM6G;0p549UKQf7q(($1DH5H z>TiVCr~Ep}Dwd~g{Zw7xv*7mK_&T_I5UofVfsi%S6xjCuz=6Hxkp*}rSYnxbL2Jfs zzHq3pKY}+zcviR7hlU8yeN)d*6hBbAq;Hj74#*CNHhH~>h*)GN5C?a`|4L8hy-#Un zq)J?Unm%KCE!Guy^AA-A`y$@k5MoqbUB$zQW_Mq?B{Lmo&eH8>bw6*jC(<(CII!B+ zc6L@QnIY`A#qU-rbuhn+X0PN9Ofx+0S!Ts&|Ja6Fw@K>3vX1abfqV;z6Ca6#!E->^ z8wfX0SpX*tDDik?(X;8>0Moi?+G_T1ZXa+g=P>E!vxm?6czxX4201W%_9FOtltECpH^Wu z^uj=p2~?Q4+c#K-g6#H?Nu1?kr$fT5IneVAfP>=#EQ~PT|NoF88<3FDCFLR{Bf0C@ z?FnepL3=ZgwnO=R!XhG&7=$Q{Oih1ZdpyzjebZJey*4$#n;f8qD{!~(o}}5^9kM~9 z{RlnB6a(XX`B5oJ2$rsD~xDfIq4d-*$@WM8LOU=?yt5dOX8WZ^!3S8&e| z0>ZQ@-=WaX=}J>kK;LaN8}us+x)KZcbF}rOhjbA}4B&vRvRma4Lnm-n;}C_u7}IU# zwsr^BgU6(st_o$}q!@ThukOb5_XNcY>M!H{1Vp?T8#ETe?0GJ*uJ)hOsMR_aWj#pZ zcY9(vPTQc;m@;RZ`U%!&ovC&mqy1FQ#!VXhF{pc(6R4Q=5JaXZT!=}@w$KZUJ!oEu zKYhCHYd{GD1+YV!*beXV%E81nW0~b?p7%ahUVWWY8Tj0cbei=@TS@-#3?mejRW#35%W-fSXFAYTa(NJAi>Zc3(`mR%!VK;8zPT? zPH?D3Q!=qf%Se1>aoBdDm6X>eSHJlwNzDR~Y}bt>YrZM86@!BMd&y^spAIDOL>8DG z)Mgwl2O*RMQp6811Fjz-XGl&4Bc6O|V&>0%mM50T_{{IQG)+SBmlCtGru#_pees@{ zLLMrfU@K1Ut3waB1q+Ovj)u_kn=p0FqE32^J=IYDBJ<)4t@?GiAcYu^S4JD0i~gbh z=dy+0xc4x>0p1KLyilnK7PKl%_@6(l9FzE!_hSGYiUDiOeW&OZ_HV;O<;Z50U$4Z$ zW+P;VB9h;^_#L^eLLKdXejc0%{~gy&g^5r?M$PQBaL@#ehZl^&QoEe(dp%HmAF`rl zoxwtG4@{V`R%&tEPy?V2wOIIjQV7s@%`Rhgj_Y;ffkyo~75oQI zg@BHh(_Qb1EhZkefBhoWK&M#8??8agFBUP6xqsdMaor)4LEb7Z=?7=Css3aztFpdC z>$(*6iq!DBy^?8onF&7I?HL2V!gQRJ7Ay;gM38{79A-JL~La! zQDv+3p(53mC*u!TlSP1Pk}dh?OBjDstFlPxx@yW{!(<_T|A%rD&dRj)S=oXd3lUWAv5K?+!dr$u`h_=F;SHr{Np5`~KVhK$SHUg8W1y8^!1YAy z=~zJ*0Bb5TaM6oqW|XSH@Yf|8l-$aX;F@vt;uh~wLvLQjMc+7rwtb{$33Ay!S(gLD z;a0LZCq?ruo16t0kYdDU4YCpy4)}>Tqd!k%AJ0Ck`68a_;cGeA3F}NVo=xL_m!8&E zn;eHS7$1Mk6Mz~?>-7x9{#o8j-c_P1y!Id@B-5MXLxzx3r!70EAccE;MwXBtVhB7> z%1Tz2&Q59ir&XRQ%36eG&&8nZKZWL=1DjjS1C>`r4M)7I6d6{3iyz9dvCd2NAu6Mw& z;F33geuYxyqsLygKy0XyP{5FyfpgTe=eFj~6`Rd$+C>&}?@k+yMN98wJ4ugsc#t>p zh~?SmSbi*c@8Prk4_pJj|31W9I?7E|;*balaLF-MJXJhR#VCy4zHMEG_ly2kfhL#3 zv_p~jwKe&x#T7gMpdXtQ;1$_B5ICviW_AAEr3o5YZy{5JGt61c?TmFK{n9dCFiV+V zHhx*O%hHI6TrU$UcybF1(hG@f7>NW$8?&N73i_%N- zAQ|uMtnxT{)l+nNI4_M0_9+SCCMgNoUTg-(jeWr4Aj5(5WUoJ?a%YdFuvHeJMAn!% zuZ!zW>Lz)7%;U?R@1Vr9{%LGW^K`UkN@lmXa_(7q+KCpQiI_oap=|{P=6zJJRF#uf%CUskcMa1=a%q_Ls(U0h44>?8XN&uyj$AOL{MKsi ze%MB6WfdL}c^_)d!NvavjDF8hpBdl9&V6}uv#){L`95|nuU@Y1CGn{QrdRH$)mkgL>x zZsbTQHd`7qbEdj$uYz@i$ogCvlGf+?*c`X;cIOQr^6wQSSr=U$fTgH9*8z0{oX6ee ziYfJ72V`NyRN>>YZl{@}rjC+)soe)|6(P(CJ{!+}P-+;y0-YTmUsFvYCmB<(dJROe zCi1P68c#@2kk6_NggETy*v{YkKON%xN}{tvW{)!l^|z$Q^HT3NjY|4df+yEs<0TJ) z&9@UA-->YOSMT81*oAX{os<~;2W~@le=6k;7p5cY*n}BI;a_daxTZ#a08!` zGc~HA3yaf_eYEpr1WpxCs}a2-y64l)y1u};=s;!_Fwz+VMS?h=xGbF3>li`2i|Sn~hn!?3LwY!(C=83&2vKZ|&v#Sn zzn9F&|5AXpasBcAdj1h>ifNg(7jXW=H{uaX1D#^s#@`J-lFGH+@nQTH<+vs&AQ#8- zvXk+w!DCsbf9=XA&Tx@|SY3ZekeaYFOIRppQGt#Csml+RZeSxL^QCnLR)c>B@`qz< zG&qDV`JUDh1#QS!iBp^BJP!g{A@WDJL5|&LSm|G*KQTibLMVB`L2{kR8YQ-c!3DkQ z79S)x8s47dtu&$jyu|&mo$aGM#j0KVOlVC0Oeh~Z`7#AX$gL9t1@t`Lbcwb}}j=_9mXX($c?!k=l|`fM|iN>EW9%9apw6aw~EsHR(kT7)!gD zmUobT_X_NBtyn9-6LRc9N@(11B2+{8enKua! zJ~(^>HFhN86S>=0_{cF$(8hgm*R0)cyi%Etyzbo!VcS)BQ9F*yn?b}e@P>@yipgjJw|1|mFJ{Fwy?5a;Ew8K{K`d_*V{(oFNzv5i;~ePgJb7VKG`)5SB2Q zs5*#tqG5+|L1Uj!D&8WEHCU29V}#pc18g!m)P{ynW|aTWXc#n3dd*9JhlcUc9fD4W zuE`q}7n{$sIqOo_OmcNk+^>Me-~72u-86hb#b@{lR?e?{o>Z)TfA50H&NXqckPV7( zN~mEigCxt(I3k3HV;5YURyj@ZyXre=0}I|gj1$=6Q|Z)cH-fh(vaNsb)yzD+)X1=3 zQ*XcAg*Owh#&mmlNsAo#!`1g$=bJF7-i_jGr$W9)Rw(!6)KuUc$}+$f6YnQjj^3Dpw8cfXEfK-sFL|>nE1GSmeLzU5xCGo(cvzSSrpa@MkUV{-O>QeKxIXJ9vvCr*7RSK6(gg&*Vy6WkpDnY z5d40VhguN}P)_(5GlfKr4RiC;)>@>BsKyTM zHDAH5?{$rZP4?6`M#w}nJJ_F*7O+<{>t<^Gd_*~oRKxLRcS}y$({Y@OHQn}tB86Zu zclvlh7Rk!Dr7}^DuaWT7o2qLfJg~n4C&W)0d7McopM4ndZ4W|)8hLeEQm5Cf9@5!xg0+6(1*X@b;kTbb* zI`PZL?-Tsb(yL(TjCkrW>iFrj3*3co%Lfji)%~fB%*cLE!Dyi_ zUp+ZKyZz=7nmiG`i)IQVrB5?&%}a94bVbx>?~%`P+JT0)&S5OoNPM2MnNokmoog{J zc&b8wo9<+zmAiZi^_yDo@^KD&Lc7QEt=(56EFOIpVJIjLLR>fnh^#}~8T1a@qS2!O z0caq;A^#5O-@@!JZ8xUNJ;&*p&uRk&PX)h>U5%WY zFsL~mX$#)k7RPmd=r9nRT$i$>o#}iTO*v}pfY9YAq5hLjyaN5B9OPA?7O_3HwQ1xm zG|mHJ$&KXGHnyl{{{R4gghN2Uu2Ww+dw2QQwl@ql)lO0Vh^B?h$@R7fT%HzQN7iouY~3+=`vLQhD{$H&S=Yhvl)-x_06^g68C1ZE;i(<2! zRg{kyn920Kkf4RwUvNZA;*}v+tVJlGH^aiBpm?T~Wte0a@eG-b_VV&#l0PsF%(o&F zUH0;!l-$3$e)L=%>zExA@ZOhr`~H7=!rx8;Z1fq)&D58IJtK@F5dJVOY+1^J4uYHL3o1UXCy3P8@9W}Z@b%U3)Bw6WLJCVikz&MB zfeDVWN&;qQ&`$JW4&LjL`-@NREMVoOw6`m)6TUCcQV>RkbOnO^ppowfD5JEPo`n248d<57#bDfb;XE&JoXK4D2v;MN0FBU3)1>DUky$~hGJwB;BN zVuY?xs2~)iliL2_qBLhNX%DGfrs13RL&@sLZ(6LQx7~f!z+hW}QZ#Y?uEciz0E;+E zH0hzjZ+>=&15Zb`^4|xFwl4J3NJ|2UrM4xoEEr4*EHjN*`x(ZXTVQ_uD zW#kD`Y-sU9A!H}P>*QZ5dj@foI;a|P;V}#bciuBA0adtWM!#E{@#(i##j9tmZi#D5 z;ZHwXI%9<=>zq@5x&o&kJG;?s3HLoh2wFC6;7wa*(qqULOr?b8)=yzIg_rqmTjOR6O*U zi@$zKFjJcBztPbViag!{ur?dTBq*CSmb@Hs*ajc%DzY|J5gQC`Zb-5(C$~0@F7wn_ zn&HG@5rx>@!wFlQ!Yj4z2J#^P_+;DsqjKPnTF?rZy|pp=iD&EeY{SorQ=`|CE888m zUa|E$%XOzzYDt}%R$(I=d3v@WVB+lu8bvYKvO(FnVLB%5ZRB6lKMPrr6nS(X9x#Z^ z^g3)fx?#mkt2rwb|0@ZQuKXe6!;aV`9kXI($Pnb;o{-RHWWqV(R}65?y;sUaq5PUV zYj6Cly}!JEe@^py&B0nKkw7bbxn+um#aj_Wv9Xef8xuFKC-8}0EXI?E7CzzV1xockoD3S<9ko;T)H6_0o5xt0O&ndo#nXQ~z7dxO7kTYCovH(E&w zNWNwo{9-iT>k-YJ);&;z{@15~p5eVrN9eE50d$E^E}e2GwsKdSwDW|1LpX7F8GBT; z9uiOJtH3AJ+b5sFZNd!BB*h`|`Z0ph@=13$v$Evyom9SHO=$?!3*E1rJE40mON3}g zjhaMjSpVV~g&-nkM>a?v00d?GCO~Ej!s0OZ&nxFQ&-h)cO*X$d z^gY`=tKYHwOwBo5R~fL`@FI6&SVi5XpikSp?!2D2zt|QY<)`~F{UOh*=p!Yt{Wliy z_H`ciaeC{K(I<5a{VsP~%=7WLepW8kavo zBjXVeR_=%HK>-moRRBT$FLp`6GHaUc4DUm<8QuML^Im?@x=mD@T`b~O{Md_4HnHP` ztPLqyniPaa!V^(u%2(L7_Q9-=ZC>g)n`8KcNpaPj1yh5qR_McAWs$*J{GhkE;lSEB z0-mHv=yzC?+jme?C;}9WM(Azn3`@x?o~N6wKJRdd;VqkOo@dm98Ntl`U={U7Xi~+( z_j8J3Hm0$Z%7n#=uZ!zG8W__sZbTegECa7VfoJV7g!ps}F;4D#6GMl|^7>WJb(6j* z3kX9(FoR3_Z%Aj$#WjrhzkSZSe0ss!^OW>mIygE$<&M$S!GSn+A}bB;O?cmAv%3p{ zv*>;!=QPEAl;FN9W7mMa&hxOna!L9)hb?P8g=aXWphUSfFYU!=Vy~{#BIJ?fckd$O zma=Iq_|9nF_674zuNef-?ihk+w9(ox>*Md1FYK3YQh0=&&iD#4=UwjvKe6ZocMLK% zOhRLfKxRrW!e_pE=w2A)8LzcU9k(l;ha~B9855KL@jj))WtG0CDnk<8xRz_jC{>F{ zV0FUyLBLbUg0q5$SW#6~caYrYH)Zl)!OwekQz;oq^3}Tqw)qcq<7;OxHIO-ODY@Zi~o`e^hh?#=esp08YWgSsy1w~Y()r?M?IRJ{^-?$%sD=rX!mUIZ8Nl$M@M1{kA09#TJGs)N1tHc3B7&wKhd^cn3{1Gg=6 z_43^}Uz`$)Sj6r42UBvL$5M`sbEV1kkPsX^ZzWUxkL%@SzU&67fQubw+`pNv#xC!h z-cBB6T362O<}^;ptW(!9_b0PoX^%h5yCk1(+rGInEN#VZZ<)BZwUcCiwj29WdOoFM zYOd~UOjXusRzihVo*0XXE{XPf{+E+qyih4DGCEz8U$0z}m4YsUYJnWEPm1H*wHRzj z2r@%TTR@$Wx`=<{k+8SwerF8WQE_a%T>kpA<*c#T_+X>&VR)un{rl~i6Vm!~>nmNZ z8|~8i@T>W&j>JdtN@fFklwuw2uru_uSbol%?_rbxz7ZYPnC(0Z_Y|M$$DB6pho{{% znbEI5-)>Fo32s7&<(}yOj|lJ1GPC>xZ-u2Xvs-{F0|pO0FPT5qfipGzncPGr^1ncCs34L@ImpOV#OP!!g#7ZEW{fB>|Gq_5(+dR=oxP7u zq%swY?lV#lRmca@_h?y+SC1K!gY2zWR|`$g9k>Mx&b7Euh9ih3(>~QUL3C%xO7a1Y zm;)hkI9#!ObP8c{U(o-qANLYtyy1a>^nz@M!P6Or_J!xzd)lUjGw?dkN5P;4e#8$N z2b&qfuq8|Q&s1()Sl{P>=Q!Kwq`H=>G*PB+Of%pY*k5*Z6EFhzTqp7?_iNBT5)ok) z&|Ba($>kiDI!wXn4hPu%-Yrfr<$6M=SLzjy-;caZ9O5>qoTaxEFBE4nQ3jsYOz%?P zv#-k@<5bh_H2_YqOfx{LLwW&qh?R) zYIqSN9q@id=0%{et&AA1`t3rk~rgrF2dk2j#xchJq`p01466ZT9i2 z4Ez2a8uFkaNxm_dj%k?IeSI>D7ZQrqEI0mz^nOf+jj|5}F0OzD zfKv%HjS#adC>3>-oAav(#3FH0rhX8bu;69zz8PR=00)mvwZBY^{5=t{7fcqbZ?%-N z!566Qo5WMctDN9G;;D1F$E;_g{pH&Dh>W6hy7WdUnQ9m0H>gKd#o{ke)F*FOP_PMT z*J6;bVVU)f)aif2)Inh=?9Gicd71yCucjDiFfE7(X$l3GU_L!hWvU zd#Cs!SN^82g4z)Z#weUz;5oV=?AFrPis$?OYR++FK1q&??0GHic{upjTk8|W z$guI``=!_){S_YGpu596PmfWQ`WNoFAHgApVcAOi-$EsTtUUwf5S?rJk3Zbx=sE@x zOdYEFbGX~wT!zrZF@I{z)@7baKjyJ7B2IUjt6(h!M~{2BD^!i%>1(pdPi!=nDL$Pu zpC)t*KeVo$y2o<$-ILxV%UB@3Gulwv1MWYa82)Kh8MFH&fiV^H<>yBa9Ox7Es;)lg z0;9y%7AU0us-{K2!uerSAIKDy%(-|G!Y^CdRP-ceA#s(mfN3 z{j-r)lJU}G*dy_qsQqk=0cu_4+|<^y!`aB8;q%u!`n#5B@lC(19?>YC6j$_WDZ83G z^M7_cbtneSJh$zwi}NTxT}!qtegX!6x3%wluCA<(QVKClMTx>tp@c6szJ)`X}1UUr1CvhU2`}j8vM9_&%t#U`g zkiW0@g378%SKA1Bk3I3-5?NFm19(X5h{Rnrwz4zK4H;%=ZqvlT3Ow#`+WLrrh?sw& z%ejov7mp!Q60lEn)zm;NHLhSL25iaFua#+U7Z-my*^}JdbgjUm)1`~!tNPN0 z$dDxK2ApB;-A}mlnr5S8K-w%dVX0_y^vOEClpAS@+Hny(1+bQEHB{rEQ`AEI(gfD^ zoTl*IY1v0=v^sAJLc}u?V_30?8Wr;jq!NjQgg_)oQGvvRN6~3Bs2wm$@gB*j4q%drInNFL2e%u5hqp#YlVt+d;Gpf!;40LX{90Mw>TBsI8*Lc5)z zAf&NY{|4;Q&U^=MG{DD@@?FyMf~Ko6g`E%xhGR4+*D+<46A6D!#9iLq)drl26X@Y_XScgM*IXgwa;!0;^ooCbFpNU@S@4((ZaVN~ksq;>_%aJEb2Q(JgfV^u zhACLnGYd4>p}#iE5-Jei8)9=nGTYtG*ClDBRzp`roG#$zF zIacC-aRJi`Q$dThLA}$u({&#`>`C7ZKnSp;KlsRMPHaEYaRgQOk%l9xX?m+JC( z!05Lv-Y_64LNqtv_g9c%{${dbg@Y_G_7uLJ+r`!GL-E$Zi3T?3E8?n8m9G}1cSk0Y zt6buj0D%IwxHsqiLAIr2mRLlerIaF!s8tb`72sHCoBK3chdr-zoEz;z#Ss(1eu0*8 zkO76vTm}SU1lyrdp#p1a5K9Y_-k?R&by%2jXH+d#bzbhX2f{V!^NmU)Ses)*`d}`xiJaVvZ4iFbL++;OUDT`2fo7d|k z(c`*X$v&T&*O#=nrN84GiHgPUeO0WRx z&Ve%IVI@GNo!WXH{HDZN85?1)z7^|(jN4TOc@U;B4-lxO^Zv0{?V92e6 z(wDWT2u#-(ebz0p5%z#D7D8ZQbl;V^D!tGDA8l_P7UjOaZ^O_b-O?Z>ASK-m(jZdO5+dE*-Q8W%CEX|> z(kW=hM9Rj&wXFld1@8aPBwE)w{$i$!23+j?oO)j zBinyqBQ}BH-e4PRY-eIv7~BW0u5#QnmnnR9M5o$HS?LyblT_hUsIEh;f1fTcEJ5}edbm25z5r_|AuM`szp#`5T@tX4WhY^kzw1Ejjy`xPhic3F-$rQ zNi)=P%5y(HCq++k;*tzcLGM+0-(W;}KN9YIO$5|-loYG}N${G1CQ1teQj?cq$T_#; z`>SdO?Gcc_xPQNZGN}Hr&8Kcn;w0~Mo=tabjn=ZvKo4%sSdSFD>#Efk*7t^i!q!N`4UEMt!6b+^VLO$p7MUBY(A)bpwaUIP`ZyWwko+1EOyA1)e| z|Fm+{D-9!Rxs+Dlqkf zI!({gjHea;?k_-`)>o&1za2kf6`6BN(yYP> zGkXL6$ncPR0-C}@BcSC++eF zPYtzXIvNzrNZk(fQGDK-8E%c}O)@|%cf7IQwQi%3?t%n>ZFK)Duqg{Q!r&@*hb=wFs)Frp)HdhF< z&WNdqARZb7#+!%03LYkiQUuD^Hy{itWn;Lz_dp2g{19`YbgHD#x@qE0U(?>JbKCMFU(hY=l-_QjMNyrqvWojbk6QY)#xxx%`RIh+(E&A-;zV^=SR#RxL84Ga9Te*K! zFzAB7BJKAK69GAH(RHhb6adxu+aW3v3D{9!uyk`>%r24vCrF8J6FsNBFM(sG{8K#D zvz4)}!bqjn@@?yb=34`(nDK}q3C0EONZZ*~FOVE3fFihk^OA%6<~MM>y+KL#ybfrM*PTStruJed+r_43>B^mfA+8 zIoR>r?3}rzjems!K8mb5mi5lPLBChjME``FrOf*f5D_^y)@u1KL&km~Qc=C*;{~vq zK8+xc5h)=|o;3-#F;3l$?*BAo0P4 zVSmgOVO@KZfdSchmU$v{VMgmdqt33j(7cYc zy+OK+OaL4_R9Xiq`b>i&6~w!YsQ4Vq-R9ME^Xism4mlgvn4ZooIe8|WeS<+b0>;l738oXAS>hKY=OihiBn4Llp}#l9D1N%n;O-U{d7%{Ew1+Y(#hAZTm1fEVemZ{aaV2VYyYaO z{v%p1PO_5`AmGGIyu}9ye24*)MIU)f!h-zte>_y6GK9E3%DnbQ39Bx06%rX?V9adR z?Y+}mLu4x-NQCHcgdPps=%9=^@_Z#*&FyNleb zi;J59!ls%VmBCiJL9SPA^1~SgMs?uDg3FMOxoJN$w);!#s6WTJaoGosA8-OJA z3SxwAxnFk~)`tUwvNP3qlg!%W8w9f55OA({3qosDAom8!SEPPWQD|5IrCFgvAM}8L z-;Pwb3q*|q0qH!F1qDGTLkjVZY{rg+m^*TBP2F5SC()$GlyvO>L0293!sd5R^$*UY za1}ZT5Auc;Qng3gd>-?XK|U+CS?2yb$9izys%+DNJKUndTC6{KSlTBS5@7g zw0)jZFUnw><}z))+~qkKzx(54coWmgu1*|z_P@sE+VHTM%fF@KA#DwL|ijR3z z7O$j1TUIMq8J$hOE(%mzU_kKMq|i_S)INL`IEB|~)ePkkzq?%pLo+jdh)eH4ZQqj`{HS4TAa1( z#4$Jyb-sl0WwE&9H(Qr$rg(%-EM>$3lZdf#b;$cnI}9}Cflaae!Cr-P&mxEnm(kG5 zsym`HKcFdpoLp~BjSar?Yf~k2r&tj5Lt+7%G{X#cD>`>Q+&(ShMJ=Q8!ku8oG^tOm zQ#OI;*%gDqicx9#Na%=YWcYZDy8&-ydqf~WZ_&`Z&Q%CcaDVCM`2mCHK%~gzJPK{K zhGkNy0_Dh5hba$c%@(0RxAaDu_QknI9WKUtUPed0LY}SR`J4)#K;jynW)@jFZWTNS>tQURc8XTMP3B0N2pa2gU0k3>HL@u3R}rW*o~q*Mz2kw}P!ghFpr zf(pUt_cQVbg?B(sk+^!Wz^O>&JNqZ70RoCbKVgG&v#aqRni5pdkY2#zcnvy=f7*Ax zSPV6P)gk=-6N*TfKq2JO>==Gg5O9fsu+|k80sgIho8f$PTk*WMgG#+s91j2qb=spdSy(^WF( z2vnm%pAqstND|bhhoKA7^};NhYoD?JgOzU{W49=)I&$V7rPPbRRqvb>F7$MGo8G&z z`sBj)+U%P1ED`}8AqtTVo~gLddHh=EXvjL=JSHV9Pjd8gfuMCRRb%ku1$#?*&EeM- zLo%#o8guE6b#Y@V2rkrVh~``oJTl>h^BxFV1Z*2!uX3#C40b zcdo9J?J(UKijK7Kk63EQ;Qj+Z{dZXGJr?t?`NdqzKTd6IZ1)ryIHFEUvA zyH}$#QDi$=KZ_4JN*;rWm`PJ4#Yur%9JH5?K!HYTEh1 zj#Jn4epk6Y0EiS?+i9I4_6~}8<~D{qyL}X&y*v1KxgurqMgZ|1rSJiD{kNO(^}~`> zB0HB({wkHz{!cH#lZCSp^OmYQX{LcLzE8y##{WID#d&3E;L>ul%y2v^T5t7RYNaTJ z@>njAGQJOJV@#KedA{s{fk9+vLm%~q7KL4{r(cqDNUCFAB3A$Ca@GdhrTZog>>=Kj z%`fovcn0RfrxxvV*?1er7Fi@kw?jenqQC4@9HUYJ%`2cRSl%yj|J35*kP{L9-k?Yf z#vrh`wyX_SxlAwmI{8_f#8`V#o~|_hEE7R?q6$1EGAxj!(BY4cAxNmj%LITFs+!{Y zQ~Pc&cb^m8l^8CBpA(7Md*Rx>oas%DHDxW=wlCtz4!7O0XByPv6mIOxaL#w$Kf=Cc zgNtW)fY121ZQoB;D|US71~dVvR_$}i^Bjq?V$mx@ZdQ+7)a z-mxkzNv_janlk{6N^jTTd~vYh(cWfvV>ZqS*1WZ+na7O{ zH*ows>duM&I1p-0?{eVV6@&l;HZin<7Yq?2@@IS^*w9VS{J$2b)<9rP%3o90?m3+; zU)+X)#38W$lOA;$>iUy58O>EN&1o%VG!ZS#)N02ar0t> zD6!sx5a0KDAjnt8HeMAx3?_}JVZ^nK@~tzF zo!wsTW5AO59H73hjQox1q%W{}8;(a5h0oLsfz6-4>lw*+I3F90GX z$Hv)V9U$dcR8N|9n~}f54leoD3=_ZTlWv#WaQUhJGDPb~ejXP)N9iFljr7+7Gldf! z|CBZQ40-0w$*lw0O$3m75tjK^H|6g8n;Y>7)B(-+lArGe`G?YjOeRMr^NrMK}|lruKno zS;)roz{G09*<&R8v`h0c(DtnQqB2(0Ckj@PV=ARe^>9(&z0sn=Exm)GH^!nqbOP0R z^H`5cX{~r?#-YVd2M2>BV(;fkT#D#kVgaxLfS(N~McdxL-62;-z~q_2{+)07E*PtY ze%SQ6fG0gzz+!~~Y~Lz%wx)d$&#r!2ouD%<_-rPtk37cCDH5AV%E-RoLOtd4fq=m2 z$=Lqi&q$+y%(%4635&PxNQaX|U;sK7+Rro6|Kj2Wg8=_S2Nnc{On^PHC-$rK-2RZ>k{th z!Y>uPkt)GQ=sbBSFn6Iij@2MGxjcP!B@J4YF z|5QwouDZ}t^B(xa-RGc@A1Fbsi^Bcvl1)ZaS`mc(Lwwvc3%aL9>98f;e8Ki>ieu08 zW9D+zy_Uj^xm*QOksxTfsE*T3{OB)yW#PIF{J}i3j&>6_art64lw>%5>#Yo@+Y1@_ ztaDsX^5>4L>vt07We%o@3(j4V_2rdc?&Nb@mhCSdf90(oB4D)n!`S@4FtLCJHOw@P zMM1*f8}@mfz%ZI_EbL!qza|ra7&mnKdpiM<3}WXwtKLzkNFWAIxN&;Ne@=UvjEhT3 zeuP3zy71~;F{jUW;=B4xU2%Ov`Esft!hMsfr0Q!hXJxH!WkK|b9!0c&-`gqof@UQ2L(Sk!Yf4uoum8pz|6bsh6dM^9UgrTBj>aN81 zuJ^Nt^?v`!ML*v2n%5W?7NiboaFp3vwj6!HThpMxA67Du z4wBARx|;h%TY5)k!)NwU^hIQIk<^8)(@Oay<0htb>HusoyhjZQ+@LZqu_rVoce7%q z1s|1w+`HTQDR;h2@Q$%#sGy%Th$Dd%7+t`M`*}5)wl0=UZ%R>Mqje}3Rh@l0hzs@l z@9w?`_Tmd^=6uM7k~UT=W9?sCU&I-tJ|`rG$(t=Kmyw*Ey@FexKYq{80CuFUcZ_IA z%F=#xU3%W($@kp;_O5UIyuWxnOu~MGZbE$DV2N_C-oOG@1iVv<^f9JNt*z|I<0orh z#65T1&%i#O(;NtEF>DX@F1pdf^CA#~-@B77nxCA+ZoXj`6vEoLcySAUlD(hp;}(5P zUwhBfd6v`!a5*9Y!zVfBQ*U@upw<)jPNoTs7Y>tq-!+@(bN1iyHA%LA-KJ+%&7kyzZ^xTycfNPq)W;05?EPn&`n#6@18Jxq?EfWyy>B_|t7lH_+QUHO!1517 z1})|y9CHi)z#G_Y?$dK>LBXzJC5u5>grRyRP4l4|BUjp?nJG6wZ!69Qu`J3bE8`=W z@+m#z3yy=9MVLym0u86+Z|rr!NnUOb%jKP=G?YpoXrN^SE&zigtzYu909)PW$`KZK z8x(xWQ{}Y9Y(5>2W6#-a_k#&?1D#vK=J@Pomi60s;VHD&{v=%oq?U6U>yuXT3-XJC z+1C1UeU&;8kivvkojyTGQOF4Y0J|Ol4aM7$6c&qDe(#@anhf^t6=!$`x2-?BZ;=;a zk>5S69v|9M`zk}`6~`F+v;tceTG&%Wf5x|pVrePx3ESMqVOjeVO)jik4*?N^W!uCm zo%O9JQ5n6T@nufwjho#0>x2R#j2UB^n|X%bDpL)jJd^_iAtSm=+ zTd>wbi_+081DdxEzJWcX+OmZdBT#zv?b%fpfdM`6Va^%s23<5Bjwj z$F`^0Q_ETosYc9Swb~RM+`&<~eT?I0qzad;oV3qv@oeSHcvMV{*ofo2 z)mW01oda;+lSb9WwdeG^Gp?os`|H);MI%tKJ@81-VOw-_4fRY|H#^{4hY$W@P-A92 zUM;2A$j9(joyyZfFQ9EC5yz{8JWVV^;eH>i-ab=D8 zMV0dc7rsJrHOn{i;`W5l-k#gmu8dR@XX zoq?D{+)&ly}~%39usH!ow;miT>D*#CWOqZyF^8~n$OF*Z{fDuA64Jh%@K!GC{_ou zJT)nd=HIWo4Mk@mk8w3gQKCDylaSRej zT%R6Mzs1wl&D#eRF6kE*wEhnnj}@Y@Qod#=CWjqe4}8(^J_C2Snfj1$kfKpZmt(0# zQ+87tW^IjATKg@I;>0s()**;Mkm$3jR;TiAO%_b&ksmXEz8q(~(Mbts;Z4DJ^!End z^hV9F)GzSwVvRz;^vheK*3DLJlBK9jGdojsC}zuXXmL z9ffGxozZ^E%is2<%({MF5Td~$-$PWv>#E=8e-Iuie7YGKFDgw;=wAkeA>zb53@Jj` z$?r-PHkB^ul1i4a5w=$23(4`qk57e`8Cix=>H(+RReAU*Z-gKVv)xOhlB^E1yY#Vu z%x(hLcWEfP^S-i%#W5Nb#Bx`A$_h;)mb@2)HHIv!(hm#h@Ej0f0?gs$isX_Z=+k9Ucm0)QnA@4kb( zlki!+EYQ4XV%0YQ6^8{45(DzZ>%yMj@@_!5_&Z1G>cm(Ch!@*glmM}~b~M60Xx?aG z-1<|*Y+R}p*}Qd085OA9L%Hq?BOnC8W1#@a`asl&=M?(i1?@sK%-Js62Rq+55D`&G z05CX8zIL3xnS1($8Wn>ICyEhkcjT4HSpC_BZ03u3^9MKh zvR~LDKMAMY#KV9t1eI)*eac?c=3k2Qx_zz`^6?9X$wTtzwj*j=x;Kj=t2Gpf1f{bo zMMHux0B@eIu5hjh&|^pZu$%oU&QYNH1BL&TwBnj!X3rDsg0A32GBr7AMDY!y%kW0p z%Z)Dd+qF$OWzQbxn8ee^O}PZOr`qyMr>@zVFN2bQiIxcRx^=*F<&)U9h4YPOswJF3 z#Cbvd2WC(BwCBjHkIRX32cuiJlkI)MkIY_*?Q3q`R8SNQaBJYR_DL(|se{|C3)k&3 z!ItN})o*dk#^RM{Oi`)mxzz}p36ZUY^u6Fw5loo`|C!MME8k3{ZUhn{d0Q8 zVZ0Q$?1KEAFMN?c86!f%-H;F4>ty@INF7E?Y|P@ivTx4y(e@IF+B^CNHmKU$-6|Ob z0PI|8G<@~Da1a}lmK6jDZy5h!ilImUH0FV*I`!49vFGvZmP3h^r>G8h|1;orFGD)K z_Jv2`d|)&PIvA80;)TTW?v?tiHFE#hqnMR*f6B{f6orv8Uh)S_YP#RIEe{S8Gz-nr zXKN^O-@iPkZFU5I0?!KEk%mj0uHX4;ThpZ(&EF)X_o^3!7GH-h{@7Yt^L*Rv0ud0Q z6gx3ankAEfV6;nf+h*i}MY;KnISHu`62zgIZea~?UEgf0aQ(z=&~plcQsKvObJwnm zuWtcGiJ?Thb=t@FvlR=5c+7{NEOGs{-^XD*@Y`U5n1LXNh#;RyjY&n9dL6?Zp3Rrv z5h9%ZiHU;(n@}+7JkejRmaxb98kt$3w5q-dpjLlH&2Eb(pHCSb4+3k>gyv)BW6j>9OJi@7Vc) zJwK6+^!pkx2C!*G5)ZKQ(buX_6!hBd#Lk0im2Lz3tM$PLt ztS8%V%n4@2PO&mB08AWZL*6RCWKEvab(>$FG}Z_>EYbYvD+Rw}JHJQ%;UxUl^vg z7a2O@U6|8%r+)>Ja1eL2?&$Y}m{84rDt+I}l!>aGo-Hz#LJ$G|EU^R5_ z?GwvdB=c??P`pweHN%{4=h-1#tb#=^eEa#I9Ug)9EH*Z-p`qQ#2=LqMdt_!k9sqCg zQ1vQI4!9k{K2M{*1m7g_ilum_xt&GObv6hJxeZg}Cw_Ie!<+BDVNODE9B+SKWspwh zd?rF%bGx*bj`hfasD%BF?!oODY{2_vDgk5u+&y_0_EvjToXgu@DQ?b>aVOiaVgLrM zwzCI5g1pxCH2J^$?H^G}-dmglfa-b6ecK%E*Ca&vg`E(VbW0J?tJ&IMBLCm}WPgz) z_oGwJynFK_P5zWNWEuBYgmJ#Z>o2mJtCfjWRv*Os^*IV9%OgIQWELy0 z7085gkq@I|BXsfT*e^nh3LQoDYg=*5;2u$a6rU!(!{Z{>J_WUcGtWnNonGi%JPyfC zsiC`lbb0GGOn;j~e|0NhZsOw+c?G`Qmwz`bm3h;vW$PJgTu+8m0mDe6jVNf2t&uy? z^!RblhhSKOVY({p;oz8CgLSn@zI?2 z(EAi3gv_%gxw_gn{2mV$cRMDmH%?x>>pdwFJwpJ>J<_FiiPe{UUQC6MWHnIlY(c zseJ;T9?8mLUNqxP%KOSmyTWfbF{B01l&HBBTD`g1qS5Hag8p@k_Xe2bafhNjFv0-> zciA~Ue!fv5A^%Jp>%9*8$4P8-S=x;po0|EPF|*UQcblQ-E%qAHPtq6b;=YC)OxVi> zi|SBf7~{>JeoYZg053Dgs_AwL!D15MN43+vSG@t)r64rkKR{(>=~4JWUll$&NL}-Y z+#FN1Pz_E}A-i=n9i#>GZDPAMw(c}zy!Y!Cid{TaDN9qjtO=KpKkhgFQNTh| zI_{2%v&YedSJ&P42js zw=h?7$3T-1L>P1ok<)cPxu4!P5p0vQnn&Nu@_~y(_HTojzYCRpbkn7QQyk!M#205X zsf@P1znMhDOonH(x`?vQ5ebZnGGg|m9?R%r9vGA~wLc?naMQXerRoKTi0a$dnXCWyA+ZBRKw^qqIW8AW}+jhxc|wws_(k7+kux*;fpc+~K>|9!?@= z$eVs85~$GSRpWr`9``zUv5@->zuh<+g;hgTG#O0lBzKgFRd%OL&ZyTP``p$@g?;sa}%FQDa`Q}X9`yTUMJI~Vsr}~wffTfuTfueFSCz12( zS9ZBYY`sm!Tj$?K4)ZV*9%_8aL|Jfw`0sZdPXP#@UI*|<@{h8W)M*d0=bXx6k)z@9 zqyOnma4_^VWRN5X{n_P`!;~?RqpAd;WJdq*i^!Mn#bMC6B?0%QkEl=cZAFgjGmn%z zT#P7W!(`wbQ_e0gKOPhuf=ok>M=-z`gqD;2UQ#IULpNOTje^F2AgR!bpijrnBQE8` zj*aHG(@Oh#=0&a1pm!IS--leDGknRPEb`1@t(H4{(Q#Cgbh}_40w#e<(&{R*QM6#0 zPPQj!S1Ov5 zD?3#*78BfWOwA^{ej|DUwHewFXv@VFsktc8VA6D8R0Xhm)u@+&j#6-|X^A6k8vy;J zK9!V|HjyOwi~`}TyW-%E#0gK@btd?i(*SO*L%q=vwI*bIYP>qZ#YoN8sqB)q>(|;MK~CeUspHGOQ?ergj4)xZLv$?un>GchmMQ$;IHLg zx$w|he>D?DxhINObOChfT1M75#5J!~O_J&n6T3Y_Yc49Oum<9=8MA*S6N`A%j&EnCW7B zEn!#^7CF0ZG^MJxm}KU3g1L~gI%obrmWKh&k>6)~OEa@{2TSB|ctkBi(x1a(pfu!Okk@U!y5jlMH_DUnQ%-9yO9`ZS!G(-Zv zWlS)l{wc1E1%l1USR7R19xWFXO_Us7%N={D;5hafZ$KeG8S4$qHw|BxCcY zV8sHob1GkFZyGCJ!-uVXSDZT-LO(1gee|%;k~cnXJ}l^?6ZdJL$A5*RSN)3%9L=&1 zG=4dq4)+tYrBflX|E0p(D+D^~9}HR_nve*gR+Lv-z1hx)V@k{V7IgkX>5CNfGep^q z0w^>DQHyj{$zz=%A;i|TI&j|J-Pp^*K3;FKu9f=OqJBR93~c#lPSkC0>f>1goYV4( z28B)tQ(q7#_GLvsa`-F@z6j;=YpqmgdYf`m#8W=8-8-)5`GZ7|ldj(R zd`kZ7Fax2659QCPHqKM;oDni}CAd@>?ij#MpNvQM9=Qk(C#TkGm|Ob!z(oHNoHK+( z9%e@o9}E)N`KTHLMECvr9{ZbQSwTR-L}TERP<|6JWrh-hM1;eDmV4suPA=`P!AvNN zr93*#AMiEvG{Q1ca|oKZ=iy^sFCi`?&PPK*09X-Ey2Ez637iN%OSB+~Ozm0o%?=W; zWDzH?Tmfu5x>lEzFhQx`xXa1)AmC7VD|HQogB~D~>x#0oQxcG)Bf>#u39IZPu>ysE z2oc|3Aa%Dh62TE z-u28@nqV+eRvwL`xs#4IuCvegKDWeB4JcB^L z5mbL;r26WS3Bh5go3++B+7H$)%C_>hrj!)cq-O+LE+mLEbpY+%a84}D4UFbQr@3RD z_4qch8%o?J__&~IxE=FiG|$Pa$-ikQ5^p=$dO%Xt<}d0OUZSv2MZ=JIyij4NKs`W^ zo`sFcV*v3vkCC6wnhbDr$ko?bEp8!=#e}nfQny{&EL^28U;|*sya+`@NeRA)nwla$qd8)?!s%6|kdF>Nfo)8SH!F zT$^tQ>{yC-AjgvXtsB*Q+j^iLe9WZsz`EKeqHez~xH*0;u>bJi$j!3YJB!66Kf)pZ zWRZNJCOEFhSk+KyCRm5jb}{=h4-Op~md0Maz-~z0+)-L{^tIx^OdQSTmwtmSnnCCB zmTra+*MqVZHxq(LRN1`vCVFM=tywd!g~X$ z#>oHsA1ccv6rggPOg58@Fi-T{fI=)+;S)c*XoS<0t!`lRVZy;=>_I*bGU>;oJ6t}(fG z%F+P3MsHLYc&*n5n+yJrUPkCiec2`(I-dPbKe0gA-f~P#EkPQy3evox*ZZ}$Lz2m3 zB;6ZHspys#uUX4D=hXR%3+s!v27{oLHOp!nwKZ7>$7f4UTN*dtRMoNil-#SRTyU3K zfOop1lW=^IyeB)QA~|Onl^FU>m$eN*nx8AG+FB@iLU#{fDQs83>XovXm{4Vx$8aX%XTxT=)a`lM&tbmu74b ziR)IJu9xE0cr!~Xv3Jfp3OQ6un}CokTmFN&f&#mnT#rT3$5$&ioM}!~Dqs1&*?x9e z$e|lBZT_|}nCgIOM&@mS7+x_`b;);}4sI}OcP_=b^g8;j^!fT@gW$g%ds0J?14EcT zPl3dRi_Zt%3QmF$AVdNJR9;b!Cm#T0Yu|v6cW4NtBmLcSw zE%LPHQs`-Oua%%XtK>Q`lT#bMANT`p2XU|@8NIw1GH|w96m=I@5S|yj3Bu@XETi!u z>H1?CO&}CKI=nH+oi}_4g5R7zC3kd~H04%1)tg%<)CZq2t2UPE`}@MmZ$cQx6vT z$5&*Fmm)r!Xy9%)O6FE0d+G~T6gk30L-+z?DHcYHpXXX%eva7T{_W6Vq5~4;9@bCq z)d>ZM1Y`2?Ke7FhM>mXC!u!}bmqe(@iCpheum@Y_EIF9#AImnnH(VNUD*XtV`+=YW zfd;jqi6om=P?DE*_LShoVmBeQ;`GO%?Dxf*5MD}~zv``4|Fs)9O2?8^tQxHd7?Qf# z$X6hs#6j2&;>JfeM;&xa{_G=`TX{C6N#(cGDU+U-2k5S?^;Q+W`byDd_HE4bnNoSu z2tQ2+5ilND<#WkPoxN#0f9-ajpP*XdGGP&Fy#Av&3lyjoh5pg>a}$ViqLZ>Ypf9~^ zj-Q+ZGcELfo8;PkRB@YXiNAyCc-2xD?G^PS-%t3T2gtw}THI0ZsQMmELiig>*$Y`F z?(@i>jCU+-y?#(c1OTe6*_HuC?_4|Ma;p4;Np zPUNxry(ZXUR2v=~js_^{(8N@!PTZ65``3a6c_cl@R?uB3udRoh`X9VIoo}O0vRa)z1e`5d2fDGe#<=MVqBIq)x zmY3Y~Q)!oA68R~C80j)7C}0!tqLUA#_)esoQ^M;Ct}OQ`mdtDSzX-nzEi`&e9X0*! z-46KumBRL>c|=Otz&sR8ASyXi5_(kv%)7ar9yn>43oAujjL2l@@EH5+YZ;#!f&Bj7Rz~DE=iL94GD#e(h0(V z%yfk8`6y`@5XZ+MKrgOCm+EfPklji<*Vd>S!W)Li(6WO+>VOPj!p?sEFj}RwWYTWP z`5+&AFYIU{YB>ig2ALrlTrXea5)6l?PcrkZ@ z^q_1H&oiFkt;W4|RFZma&VJ4!3l=$gQ!d&hP+-OYX4BXX{PYm@+A?vQP?02e`0D_IaB{Rtkh7hMQQDw#3R3X;Sd>yYCxD{+=H1Qy zfcGXnQwi+i%$^_Ni7_3ht|MI=IUadZxMe7(SC}?Gdhxi7XR%c}-?$u{W}IAVgt9i$ zGIyu!0slSh9g0f&&#_zbnBRqh?Bsr;0Mz4yFoiJOypw+724QzHxBJx?g1VS=GWF&7 zWeKq61PBQzq`E(O-yqij@f#&V(R}M$rl&ntWuc~y*QEBU=OE-~mAlq4snHl%#EXz{ z53@bT)ZTJAyt0sowB&2!mYB?u)joKmxR<%!Yg-q-X&>$2+;47IDTSAqHv|9vNrVZd zy^18^*JjdxQ754n0W>FSIL^!`ASU&*uoI~r<;La5*QOplwcO2BioMJj){WQxwnv2* z-x7wJV`DeD+7`f(8i6lOhFAK##0Fe{S;nK>Y>U784=+fF}hP&O5R8^CxqKcD$y<+zPxD^%OBrO`1}QY!Rkrn_DE=n$4y<}qK|op zC#7u(RfDD*y1E7$`YqFo3}MTg4@~ymXdC&$adn1>EhO-AE#pp~+$%Fqzb?>x3&3CS zmD>G|^pV&f0L+K3F;J5a--;NJt^HMPdEkRT3fC}`9Nr-*1QvqHM=Nxj9AT)&ladsZ zQ4Q@EWw$TjZX>I1S7#GfXl({22f4Kol}8KV5h)>iA|{?1CP=a(m`|3zEE{T@8g0$0>p>m{yO~KOgpc<=LwXXsSz_vrsTf zPLvpCo)TYF6c(2+2{>PQsN1I;y^YZDpMC58CDriOVPH^qTOi#YQk?~-zy9>q#;df2 z?I*3ncRGg$S5$ghF-8=~?VLH$6N+Tk4NstdAIjm{J&t^U=9YJxs2%N6;<_XOQ`m=% z}v(t(g%#{zzHARG#iHNxR6Z(Ie^3zh3^nsK&$O@f)|9q zCKtZQ2=Tom_jvGX(>+8n%aiimg zqkGSkze!+bJF1ye$b&6Omu1DI>5kR_0f+}|$)dG3Dmwkz1UPLLzJCI1Nm9Omekfr+ zNa&O_$xTMXui}Ny49GWaSHf!PvliqyMcQWI8_bI1y~tJ+Wh^9vgW*v!NSFYG&{4oA zCjv`*$Yy)&2aSY?uabm&Vlyq6U|G&R$-BgRL_!3oL4S69V8*h1@%w>c^5~pbu;dv0H}R+#r7i*mH|?R-Z4vIX)8>2Z6ipF#kHQ?0 z_t%JCZWVx+TO-H8T`Nm28}<|6DUKn-#yB7i^$;JI0uW~^%ETw`3Ht!#2=(5YkZ{Ij zIj&@yfoCL-qP|TI3nf=(Tu1bcZVJURJX+K!l4nOqw;SJou>^bF_kfi5t`Fb;`l{aK z_5aAijof#AlaJe*TWBR$Qg+d%aH0MD$cYGbajNXq);YLwL%`8M+bB+U7g6@40&%I$ z=KWaJyaNUVZEF^U`>rljrRPhtKwh z2#2`Hdk6$_d=$#_5w?7luR9Sb9~d9YU$$Py^olfpdDrZ`y=4E*U}>CXhr(>ld)m)} zhsbi+(J#~)1GBK^(4aa2_T9`wHln$qm+R|Pf`V^@6gZ>25EXSA`a~%SJ$RCv=GWHL zkKXw?uJ$`<(i$Z7N~O#aiVjyfZ&)WI6R7J4E}TTRC)I#36uhhm6e%SgLjo{)LK*__ zkmb2E`44N(HjSjR6L_OnXya3(5wI5gMfJPx)d2Jk-jFe!;)o5p=ssOgNH|0mcz!e; zhosMKF_+S|5PmH#E@~aaS}qpJYbyBaTCBb<1iWgyr4Fh*=4Dw55?@x0xVNBUkm+>a z$Xs|eS#=l$TxtP_FfU9zOwv@DKZA48845c^tfqZSrK_0# z4Nuxs8P%E7X?lM6R?jYVEm!+-(ia}p0x_vNS8dwCavnW&41McQT$y=bfdD(x-Na_c z?aDnQ7U$x-bFhX^r)z`J;8c^uBR`^bMW*BS(i_E^1<{K}aOU>3zJ9Vru4hN(3}&6;mI}I#b_D3OH*WW&KN!u>6Sz3p#F1ng=lBD#k ziC~%{sc9*fe$C5t`P?OsrvDxiAJXkJQP(FY6)JqIKgXiRfhYoE~(@g$cENuCfTYj#7U6Z!#hMg4zB1d>XZL$B-}Urpmc9N+<_ zCUFmdfl56#Fg&GRHU&_Nztb4)l#o+xs40un-rlcWGSHtDO}?8AGL&W{`XcBDqG~S{ z;HJiuBQ6a`!=z{L0IroERcH%N?rc~w^u&ez?u+AsG>C^;)*uRKsGi}u9Bm3Ca18=tC~ zEnyv(DVcKEN@vJtd+xJ{P$;Y!v4*0&M$5sx825Glqfd^AytdJ7dLXD{U#+5n5BRzMMzp0^@Zn!3uKgl)0 zUV4XW!Pvz4@iD>~CoUy9B`J!eTL)u|-30Z`W8z9#`Rg&}>sFl_euv{{-#TWtUe?SD zyqn2Ul~LuhX)m8uE{P@lJk>%;!emmd+27g|Iav;fA*qx7zRuQeSM)bDWa*MAOG>}? zrDYa#(QpM`I-kZc_Ymy+rGSM+N)QYj1{%I0=gHcuoJuc9U$_ud6s9`Y6Pp+nnj@<>w0eWm=&h3d@TqE%7Q#x8Ju_oV0uth40r{}BOB4ZK8dIZo1mqEUw7 zf~!*K@-~C^T`bk0#|s7VtBcu!ERW%t`fgven!3ku87(q`$o~Lm1-z;x^lZo>p zeX5ze;EMpGg-6y2=?_=0YyCd!)egiyv zI-=niNpJ;9`i|Pk6|WM}yfCrJ92VwgH3}CVicqYH20{q`k+A#6uZ{wIPQQLV&$z4g z(D_izs>?ws+qBD0n63%sh#+t_#2e>+|Bb+J59$U&jkiHpC=dye zNtgH7Gp_vu-c$bGuZA(2R}`5Af8ENq6~(}}Oy&qFbq>^#jKLmQ0oc80n!_%{7WYjA zul60Dv$k2YGp_zIM#4A$sjr>&Z4L&0Q2v7bIiFE>8!PV-I1(I^AIXh6$^3$OMu@1F z@W4cuY2e*O#U~y{%LPsr*z@emXP$2EeGbzDR4zwI<*^&-E0Md$|3O2YF9XKJ+o0Lxgtq6 zZe5ivP%Znd=hxExiv|;K^K_yc=-M?Eb{IZOafGB+xTRKneAJn3#Be5cD|yEjpYt8c zV<<|Fx2C*%Egq&^jDD}4r@@={#|9AJ*fVshGm{hkkA{A-()EhH0G46Xi(iR&k@7eq#TfFZYKRwT zFy7^vl;L_IP@o7Z+Hkz|%>mO*5E>u3g)mp}d&)D*qkZfeV4@k`+pW3A2u2`b1IDW? zoDLVni|y00HRK45q?a8tuD-h8JH$c0@D@|x+hgi(R-LHakYg3gp(`ccq8_aABI_Y_ zvvk`j?q`5&3HrEN&)4t4-*v;E&@(a8-`HPq8~4tQ(iKSw2>6o>a>W(U$;YPscBAZ7 zp1#2+23f?*!pasY^v|`hglM{z-z9=S9D>j^3^4vVZjLtZ59i)iO+4yeBUH{c;R~@H zhyIB0a|IcpvjeCmheI+-3Ie4+_&>V;{ArcE?j5*9VuTv&!&LNgcBIy{+#D46_qe^c zf)xMGXGS`LC#B_LtJMDty$^MGA~AJClI;Ebhhvd{q2R-U9z4K3Fst|E|5xj&5CQ@& z4%qSv3Db?=vzvdAl=*c-BY-}?`L3)I|FmYX1zBg(p0*3) zX!UgkWndrI>f}IvNFbxd5nloZ>^{f)wSA99(dgUOXucr1UI)uSiij{eB!nOhn*wM} zoiFO7e-PdugwIQ9|XZ znN%OI?@KS}-xaE5nzCbuR_y9YYrg+_TNUs(E55vO>$%K*)9fF=WxTmZ#7pO8c&xSW z`jS7ZtmnNtbAEe(oN;K*`PFt8clEyf+_Uf2-<^{~^uzg^pEQFn>eY09?1UKwO})T% z#|;7(<1K)G zPbM9XxShUjKj&$``#tKwLvWx8WfptZ>I+g!uf;|hDgu`eI_Q`fWc~G;@M-Cmd2xBu zW~KS2yEwC0dLqv>Od&Xalj6Af+O2Dn6B{moms4MQz`%U$=<7pG8IKtQJ$xc+K3r&Q zX}PmA^3lm{yVq0}eN7Qb|CaXhZRgs@+cYm!MFo4kzrAzkLSNuWy&}KO2L=`nt557c zhD#H=o@v<5zA@8rwlZVJs}}GvPB&X}snS;H^U$OH(|vmre--9>pXoYi1M>qA}5X|Ef;0wNFd0 z-l{LX@L%G#{<_+ka`l!9wv&%qIf;vSgsE#^52-t%l(OT(*PuDC*N9y2(mp%=9Ea*+ zKj^;jI7b)64M~|985uR;TawVW$UjW-i&}YfMp*R9xliYA%i6Pc@AsfJAJ0anM;Tr- zz8slWYq&2o*hl?ZiC@q1vmuwWvX@=Sss`@&&H8cWviEjnfr~Sa6o7Y2t@Q(*)Fz_* zXx195pS{mc)PA|IG1ua+{RIaOHl7|1#>(KgxxR)+EtOV&eYdv!?)R$VbGy}h6Rb_Y zE&HmsPujJqydAhH?Gk*(lIOVa%+0qxo4g8Hwgq?=cjogg^>?RLEstBXmwR{F>PyPk zK!4 zrMWf~wuL2zMU=QZcO%x@xZV^K;XI@x-adCtaQETmGPl<}`kC&}p_6pDE z$$!iIx!-%|-r^%iS-xuBOyA4?@Ab-6ufO}x+ZP`;H_c|%;;@BgS@OTtBKOM{8%zB1 lPmgt&)^qezZf#_xWV-n;@AsSki~rfZ4}AofTM;q>3;-DDR09A2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6c16b84194ac60c492487044ed3ee744c506faf6-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6c16b84194ac60c492487044ed3ee744c506faf6-2 new file mode 100644 index 0000000..c33ede6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6c16b84194ac60c492487044ed3ee744c506faf6-2 @@ -0,0 +1 @@ +FD/JT,oVsE  \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6cdd7b3f70c2448bb4f666c8bc5aa6a890a34f7a-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/6cdd7b3f70c2448bb4f666c8bc5aa6a890a34f7a-3 new file mode 100644 index 0000000000000000000000000000000000000000..bca304b2106ccf27b0f4bccf102511aae4805227 GIT binary patch literal 27 acmWe|TylnC6MtdSb%yu*_X;sGAOHY>wFavI literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/73e369adcad522a27653be74fe4a9ff8d30ea19e-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/73e369adcad522a27653be74fe4a9ff8d30ea19e-7 new file mode 100644 index 0000000..cf4fadd --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/73e369adcad522a27653be74fe4a9ff8d30ea19e-7 @@ -0,0 +1 @@ +deEd \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/7f1623aee483c22124f8ecd37ad62c5acc932304-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/7f1623aee483c22124f8ecd37ad62c5acc932304-4 new file mode 100644 index 0000000000000000000000000000000000000000..3e04cacac88b40d366fc6cc47c0330ec5d8c1e17 GIT binary patch literal 39 ucmb1&;*RFN-DTpb^61^-WxcX(djBoY_bq1qyQwCh@yQ$k2Fvq6iX8w{E)iP* literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/87e26a4d86b6f1ffba523d73bdf7479715faa6c0-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/87e26a4d86b6f1ffba523d73bdf7479715faa6c0-5 new file mode 100644 index 0000000000000000000000000000000000000000..188474c0c3344b2403d0dab9f10d528fb62fe1a9 GIT binary patch literal 10 Pcmd7Z-yYJ2wLd11G~%b;gEMj0Y7&;>w=7x#%Ch>~%CmCqJzC JyDJalQvizu5dr`J literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/94b18a8ac5c2cd3b040754e236dadeae895b3dae-13 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/94b18a8ac5c2cd3b040754e236dadeae895b3dae-13 new file mode 100644 index 0000000000000000000000000000000000000000..0ffa78f556fa27ea105edcd1f78593d54c60e532 GIT binary patch literal 10 RcmbObqNKpUz#zcD000WU0XF~u literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9835e8bdcd54890f9ff4dfdb634b5a6dc254f09e-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9835e8bdcd54890f9ff4dfdb634b5a6dc254f09e-2 new file mode 100644 index 0000000..3ce84e2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9835e8bdcd54890f9ff4dfdb634b5a6dc254f09e-2 @@ -0,0 +1 @@ +pǷ4(NZ@Dp?)Uzs֗I5NsZ뜳Y"r[Lòe"t(eK5HEV&}N9-ae#t(eK \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9f3d543656b54b38ac84f009a626bdfb074393cb-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/9f3d543656b54b38ac84f009a626bdfb074393cb-2 new file mode 100644 index 0000000000000000000000000000000000000000..26285dc066a1a9dc8c8adfcf7496a8bb62e74aa2 GIT binary patch literal 18 ZcmZ3$&etL{Lo7n=eo;6V7lRu+Hvlsd1eO2* literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/a70fe33ef1a23361593e5d25ed782c2b4ee22813-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/a70fe33ef1a23361593e5d25ed782c2b4ee22813-1 new file mode 100644 index 0000000000000000000000000000000000000000..671f84ae85958bcc2180f25b322862f83919572d GIT binary patch literal 18 NcmWewSkHh0qyQ7`0ZRY? literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ab076dfc3f75d3a603806cbf3ab318bab8575591-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ab076dfc3f75d3a603806cbf3ab318bab8575591-7 new file mode 100644 index 0000000..baaa094 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ab076dfc3f75d3a603806cbf3ab318bab8575591-7 @@ -0,0 +1 @@ +eeEE \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ac8feec2af44db5a6eafff09781dc9c922fc1380-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ac8feec2af44db5a6eafff09781dc9c922fc1380-4 new file mode 100644 index 0000000..3c731a2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ac8feec2af44db5a6eafff09781dc9c922fc1380-4 @@ -0,0 +1 @@ + 2021222324252$272829[Cæ% \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/aeb91ce9a4b3547b57a3ab02add1500b6d6447a8-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/aeb91ce9a4b3547b57a3ab02add1500b6d6447a8-4 new file mode 100644 index 0000000000000000000000000000000000000000..5b2f3511eb7cd5bdf28e63d55b8a9e6d44f0dbd4 GIT binary patch literal 28 gcmb1&;*RFN-DTpb^61@S2A*ZTmggCt%wY#p0Gd<_r~m)} literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/af04c0ac0c9608e913ab0f27a1426630adc72f57-8 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/af04c0ac0c9608e913ab0f27a1426630adc72f57-8 new file mode 100644 index 0000000..ec52ad3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/af04c0ac0c9608e913ab0f27a1426630adc72f57-8 @@ -0,0 +1 @@ +eEEEe \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/b8fceb6a5aa974b33d2dc94526c96a3d46633e89-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/b8fceb6a5aa974b33d2dc94526c96a3d46633e89-4 new file mode 100644 index 0000000..c527841 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/b8fceb6a5aa974b33d2dc94526c96a3d46633e89-4 @@ -0,0 +1 @@ +B3 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ba01d6cf0fb9c71370ef35d6c6cebb1fa75018f6-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ba01d6cf0fb9c71370ef35d6c6cebb1fa75018f6-5 new file mode 100644 index 0000000000000000000000000000000000000000..feb667e36aa55ad0968ec5b9d24e6cd4e3b6c30b GIT binary patch literal 10 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 AdH?_b literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c3793d6b45cba4a91dc18770c1c2a9946d334258-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c3793d6b45cba4a91dc18770c1c2a9946d334258-1 new file mode 100644 index 0000000000000000000000000000000000000000..684c008dc5d0cee66fe0b51441696a52b877f9c8 GIT binary patch literal 86784 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

    }Dae0VIe3$9Z?JSz(qZ&NI+Jo~yI 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c9d84a90c00d2393354dd80dbb9d26e8edd387e0-10 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c9d84a90c00d2393354dd80dbb9d26e8edd387e0-10 new file mode 100644 index 0000000..bb912c0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/c9d84a90c00d2393354dd80dbb9d26e8edd387e0-10 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d06c109bc27d8914b330b99ac8262cbceda79b4f-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d06c109bc27d8914b330b99ac8262cbceda79b4f-1 new file mode 100644 index 0000000..f3400c0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d06c109bc27d8914b330b99ac8262cbceda79b4f-1 @@ -0,0 +1 @@ +Z [j<<<< \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d1f80ef35b58a2366e5b133473dc273f3740d57b-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d1f80ef35b58a2366e5b133473dc273f3740d57b-7 new file mode 100644 index 0000000..d4f4625 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d1f80ef35b58a2366e5b133473dc273f3740d57b-7 @@ -0,0 +1 @@ + eEeEeE \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d2e694ef05e527e478769df82b0f65fb3b442a45-1 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/d2e694ef05e527e478769df82b0f65fb3b442a45-1 new file mode 100644 index 0000000000000000000000000000000000000000..e5a5b6cbb3cf9f72410e0a96e8b65f8a96d77211 GIT binary patch literal 506 zcmV-k% z3^=!5=y98)YwjLDsabWpC(+8fFbQSTYE84P)UZy|lyp)YnN`i!x%EPi+Zu=fH+eVRdFZ8(W zPqONiXk}fPgtBS1rnwF4G)+mVNL91-Ug*%Gm33hfN;*wcB-`HY2u6+_MWIVOw_fPm z-2CyAnpNkMXk}fPgtBR!W?QLYou(=2q&PCGnyqu|g}%+rAAj2xy0mlag}%+rS!#7k zw7M_}Wz#yfmAX!oq!dT0nyqu|^=)p>-?kAT0T)D2AVLHQD&Thw4Jre3z#^*p6*m%G z(bLLXaD1%2@vrHRXm}6i5uXAr>H9x^@)7?w5cB`-^ArAn8~W~W&%yW!42#F?<a?`TtBsq+lrZ`=s@uJy6+PU>YkJ}twbNBd3 w&8pKqiB{HyNhq6EYnpAPhIN{zq?6*vtZKH-trvRS=IENc$4_e8VgezFj}itAIsgCw literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-2 new file mode 100644 index 0000000..e69de29 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/db3bda50ea81814214d6e6c511736731a44d7b9a-2 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/db3bda50ea81814214d6e6c511736731a44d7b9a-2 new file mode 100644 index 0000000000000000000000000000000000000000..4b11d36b865d059bb25dc9651274d18a57e5cb42 GIT binary patch literal 76 zcmeYgTDV1t0UbP;UUJ)8M>Db8Cv4)Bd-r1Ic%-B%c?PAWg?s(JTT-sLbV`+1?S(x} Ti(Fo5ojQJKU3cd0RotxrUY8v# literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ddf623fc42f256fbee77d98e0c341d8f8e967d6f-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ddf623fc42f256fbee77d98e0c341d8f8e967d6f-6 new file mode 100644 index 0000000000000000000000000000000000000000..9c557aa056cea0de2a8b912d53415964c1e08d32 GIT binary patch literal 13 Ucmd=7km~whfZ_iq1_p^o04O2_pa1{> literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/e7416101c16988f1aa4ad09e2e0ea26698a69fd5-6 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/e7416101c16988f1aa4ad09e2e0ea26698a69fd5-6 new file mode 100644 index 0000000..be7d610 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/e7416101c16988f1aa4ad09e2e0ea26698a69fd5-6 @@ -0,0 +1 @@ + 202122222231222324252$272829[ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/eae606b8c2871f94da1b8190d095e686e9f2eebc-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/eae606b8c2871f94da1b8190d095e686e9f2eebc-5 new file mode 100644 index 0000000000000000000000000000000000000000..50170825f41456d86b816c6a50ba3f4472783586 GIT binary patch literal 90 zcmazza4hk!{N8W>F#zMswb$aUpKD5RCog<*Aae556&(f_9h}-fY0g=`C4Uct&yiI< hc4EPL?vEY>NzC+o#$2`1MPb5IkwCB6oh~X`N&vm1GqV5y literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ec2c23b0ecfb55422bb7376b9de762f0cb2daabc-5 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ec2c23b0ecfb55422bb7376b9de762f0cb2daabc-5 new file mode 100644 index 0000000000000000000000000000000000000000..11dcb02064944079a2b81adee1e7d1d9767d6dbb GIT binary patch literal 90 zcmazza4hk!{N8W>p#aYK|DW;V+H3LF&ox(c7+!R6YX77&XZe==Jq$iaR`uA41?#y# kdJrTr!Sfk&)k+tI2~R}=y=Hg1SU;Cn(NdaJo_2pO0Luw9YybcN literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ee5e3543ec53aa392b7485e16163661dc45c61b8-3 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/ee5e3543ec53aa392b7485e16163661dc45c61b8-3 new file mode 100644 index 0000000000000000000000000000000000000000..94008ebe5f13d384581eb65f1e2ddaf0cc89bda4 GIT binary patch literal 18 McmWe|T*80~01v|e_5c6? literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/f317ba679fa2f7020fd501a5ceb78a12da06a817-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/f317ba679fa2f7020fd501a5ceb78a12da06a817-4 new file mode 100644 index 0000000000000000000000000000000000000000..84536c0eb9e2e663d76142c0eff307ac4c07cc86 GIT binary patch literal 90 zcmazza4hk!{N8W>;ehet+H3LF&ow2ulNa7R5IK43iVlN|4o>Z#bmlDIlD~(+=g6ua qJF#Fr_eT$cBxZU(W3F21qA=m9NTAp3P8Ss|rAg&!_vZ%iJpurWt1rd? literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fa0258e24eecdba8b3e9355740c458120b4babce-7 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fa0258e24eecdba8b3e9355740c458120b4babce-7 new file mode 100644 index 0000000..d7bae71 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fa0258e24eecdba8b3e9355740c458120b4babce-7 @@ -0,0 +1 @@ + 2021222222232222232222314252$2798 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fab8c92bc4068e05f10d9b1978a34bfd5a0c12da-4 b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fab8c92bc4068e05f10d9b1978a34bfd5a0c12da-4 new file mode 100644 index 0000000..b22e073 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/decompress/corpus/fab8c92bc4068e05f10d9b1978a34bfd5a0c12da-4 @@ -0,0 +1 @@ + eEfg \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/run-compress.cmd b/vendor/github.com/klauspost/compress/huff0/fuzz/run-compress.cmd new file mode 100644 index 0000000..5b4b064 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/run-compress.cmd @@ -0,0 +1,4 @@ +cd .. +go-fuzz-build -tags=compress github.com/klauspost/compress/huff0 +cd fuzz +go-fuzz -bin=../huff0-fuzz.zip -workdir=compress -procs=4 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz/run-decompress.cmd b/vendor/github.com/klauspost/compress/huff0/fuzz/run-decompress.cmd new file mode 100644 index 0000000..3f96532 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz/run-decompress.cmd @@ -0,0 +1,4 @@ +cd .. +go-fuzz-build -tags=decompress github.com/klauspost/compress/huff0 +cd fuzz +go-fuzz -bin=../huff0-fuzz.zip -workdir=decompress -procs=4 diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz_compress.go b/vendor/github.com/klauspost/compress/huff0/fuzz_compress.go new file mode 100644 index 0000000..7f63e7b --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz_compress.go @@ -0,0 +1,27 @@ +// +build gofuzz,compress + +package huff0 + +import "bytes" + +func Fuzz(data []byte) int { + comp, _, err := Compress1X(data, nil) + if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig { + return 0 + } + if err != nil { + panic(err) + } + s, remain, err := ReadTable(comp, nil) + if err != nil { + panic(err) + } + out, err := s.Decompress1X(remain) + if err != nil { + panic(err) + } + if !bytes.Equal(out, data) { + panic("decompression mismatch") + } + return 1 +} diff --git a/vendor/github.com/klauspost/compress/huff0/fuzz_decompress.go b/vendor/github.com/klauspost/compress/huff0/fuzz_decompress.go new file mode 100644 index 0000000..8403a43 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/fuzz_decompress.go @@ -0,0 +1,16 @@ +// +build gofuzz,decompress + +package huff0 + +func Fuzz(data []byte) int { + s, rem, err := ReadTable(data, nil) + if err != nil { + return 0 + } + _, err1 := s.Decompress1X(rem) + _, err4 := s.Decompress4X(rem, BlockSizeMax) + if err1 != nil && err4 != nil { + return 0 + } + return 1 +} diff --git a/vendor/github.com/klauspost/compress/huff0/highbit_go19.go b/vendor/github.com/klauspost/compress/huff0/highbit_go19.go new file mode 100644 index 0000000..9d54ba9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/highbit_go19.go @@ -0,0 +1,9 @@ +// +build go1.9 + +package huff0 + +import "math/bits" + +func highBit32(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} diff --git a/vendor/github.com/klauspost/compress/huff0/highbit_old.go b/vendor/github.com/klauspost/compress/huff0/highbit_old.go new file mode 100644 index 0000000..5da31b1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/highbit_old.go @@ -0,0 +1,18 @@ +// +build !go1.9 + +package huff0 + +var deBruijnClz = [...]uint8{0, 9, 1, 10, 13, 21, 2, 29, + 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, + 19, 27, 23, 6, 26, 5, 4, 31} + +// highBit32 returns the highest set bit +func highBit32(v uint32) (n uint32) { + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + return uint32(deBruijnClz[(v*0x07C4ACDD)>>27]) +} diff --git a/vendor/github.com/klauspost/compress/huff0/huff0.go b/vendor/github.com/klauspost/compress/huff0/huff0.go new file mode 100644 index 0000000..a9a93aa --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/huff0.go @@ -0,0 +1,232 @@ +package huff0 + +import ( + "errors" + "fmt" + "math" + + "github.com/klauspost/compress/fse" +) + +const ( + maxSymbolValue = 255 + + // zstandard limits tablelog to 11, see: + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#huffman-tree-description + tableLogMax = 11 + tableLogDefault = 11 + minTablelog = 5 + huffNodesLen = 512 + + // BlockSizeMax is maximum input size for a single block uncompressed. + BlockSizeMax = 128 << 10 +) + +var ( + // ErrIncompressible is returned when input is judged to be too hard to compress. + ErrIncompressible = errors.New("input is not compressible") + + // ErrUseRLE is returned from the compressor when the input is a single byte value repeated. + ErrUseRLE = errors.New("input is single value repeated") + + // ErrTooBig is return if input is too large for a single block. + ErrTooBig = errors.New("input too big") +) + +type ReusePolicy uint8 + +const ( + // ReusePolicyAllow will allow reuse if it produces smaller output. + ReusePolicyAllow ReusePolicy = iota + + // ReusePolicyPrefer will re-use aggressively if possible. + // This will not check if a new table will produce smaller output, + // except if the current table is impossible to use or + // compressed output is bigger than input. + ReusePolicyPrefer + + // ReusePolicyNone will disable re-use of tables. + // This is slightly faster than ReusePolicyAllow but may produce larger output. + ReusePolicyNone +) + +type Scratch struct { + count [maxSymbolValue + 1]uint32 + + // Per block parameters. + // These can be used to override compression parameters of the block. + // Do not touch, unless you know what you are doing. + + // Out is output buffer. + // If the scratch is re-used before the caller is done processing the output, + // set this field to nil. + // Otherwise the output buffer will be re-used for next Compression/Decompression step + // and allocation will be avoided. + Out []byte + + // OutTable will contain the table data only, if a new table has been generated. + // Slice of the returned data. + OutTable []byte + + // OutData will contain the compressed data. + // Slice of the returned data. + OutData []byte + + // MaxSymbolValue will override the maximum symbol value of the next block. + MaxSymbolValue uint8 + + // TableLog will attempt to override the tablelog for the next block. + // Must be <= 11. + TableLog uint8 + + // Reuse will specify the reuse policy + Reuse ReusePolicy + + br byteReader + symbolLen uint16 // Length of active part of the symbol table. + maxCount int // count of the most probable symbol + clearCount bool // clear count + actualTableLog uint8 // Selected tablelog. + prevTable cTable // Table used for previous compression. + cTable cTable // compression table + dt dTable // decompression table + nodes []nodeElt + tmpOut [4][]byte + fse *fse.Scratch + huffWeight [maxSymbolValue + 1]byte +} + +func (s *Scratch) prepare(in []byte) (*Scratch, error) { + if len(in) > BlockSizeMax { + return nil, ErrTooBig + } + if s == nil { + s = &Scratch{} + } + if s.MaxSymbolValue == 0 { + s.MaxSymbolValue = maxSymbolValue + } + if s.TableLog == 0 { + s.TableLog = tableLogDefault + } + if s.TableLog > tableLogMax { + return nil, fmt.Errorf("tableLog (%d) > maxTableLog (%d)", s.TableLog, tableLogMax) + } + if s.clearCount && s.maxCount == 0 { + for i := range s.count { + s.count[i] = 0 + } + s.clearCount = false + } + if cap(s.Out) == 0 { + s.Out = make([]byte, 0, len(in)) + } + s.Out = s.Out[:0] + + s.OutTable = nil + s.OutData = nil + if cap(s.nodes) < huffNodesLen+1 { + s.nodes = make([]nodeElt, 0, huffNodesLen+1) + } + s.nodes = s.nodes[:0] + if s.fse == nil { + s.fse = &fse.Scratch{} + } + s.br.init(in) + + return s, nil +} + +type cTable []cTableEntry + +func (c cTable) write(s *Scratch) error { + var ( + // precomputed conversion table + bitsToWeight [tableLogMax + 1]byte + huffLog = s.actualTableLog + // last weight is not saved. + maxSymbolValue = uint8(s.symbolLen - 1) + huffWeight = s.huffWeight[:256] + ) + const ( + maxFSETableLog = 6 + ) + // convert to weight + bitsToWeight[0] = 0 + for n := uint8(1); n < huffLog+1; n++ { + bitsToWeight[n] = huffLog + 1 - n + } + + // Acquire histogram for FSE. + hist := s.fse.Histogram() + hist = hist[:256] + for i := range hist[:16] { + hist[i] = 0 + } + for n := uint8(0); n < maxSymbolValue; n++ { + v := bitsToWeight[c[n].nBits] & 15 + huffWeight[n] = v + hist[v]++ + } + + // FSE compress if feasible. + if maxSymbolValue >= 2 { + huffMaxCnt := uint32(0) + huffMax := uint8(0) + for i, v := range hist[:16] { + if v == 0 { + continue + } + huffMax = byte(i) + if v > huffMaxCnt { + huffMaxCnt = v + } + } + s.fse.HistogramFinished(huffMax, int(huffMaxCnt)) + s.fse.TableLog = maxFSETableLog + b, err := fse.Compress(huffWeight[:maxSymbolValue], s.fse) + if err == nil && len(b) < int(s.symbolLen>>1) { + s.Out = append(s.Out, uint8(len(b))) + s.Out = append(s.Out, b...) + return nil + } + } + // write raw values as 4-bits (max : 15) + if maxSymbolValue > (256 - 128) { + // should not happen : likely means source cannot be compressed + return ErrIncompressible + } + op := s.Out + // special case, pack weights 4 bits/weight. + op = append(op, 128|(maxSymbolValue-1)) + // be sure it doesn't cause msan issue in final combination + huffWeight[maxSymbolValue] = 0 + for n := uint16(0); n < uint16(maxSymbolValue); n += 2 { + op = append(op, (huffWeight[n]<<4)|huffWeight[n+1]) + } + s.Out = op + return nil +} + +// estimateSize returns the estimated size in bytes of the input represented in the +// histogram supplied. +func (c cTable) estimateSize(hist []uint32) int { + nbBits := uint32(7) + for i, v := range c[:len(hist)] { + nbBits += uint32(v.nBits) * hist[i] + } + return int(nbBits >> 3) +} + +// minSize returns the minimum possible size considering the shannon limit. +func (s *Scratch) minSize(total int) int { + nbBits := float64(7) + fTotal := float64(total) + for _, v := range s.count[:s.symbolLen] { + n := float64(v) + if n > 0 { + nbBits += math.Log2(fTotal/n) * n + } + } + return int(nbBits) >> 3 +} diff --git a/vendor/github.com/klauspost/compress/testdata/case1.bin b/vendor/github.com/klauspost/compress/testdata/case1.bin new file mode 100644 index 0000000000000000000000000000000000000000..723b4bc222cb7039be1b2b916bda9428a7953edf GIT binary patch literal 55 zcmWN@!2!T92m-*21frq~W&aJ@-0MmpCV}&Ll&GwVEsl&!s{75sW@D|DcM$UfSA+}# literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/testdata/case2.bin b/vendor/github.com/klauspost/compress/testdata/case2.bin new file mode 100644 index 0000000..c34928f --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/case2.bin @@ -0,0 +1 @@ +5555555555555054072307277407224532200600565 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/case3.bin b/vendor/github.com/klauspost/compress/testdata/case3.bin new file mode 100644 index 0000000..c44f88d --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/case3.bin @@ -0,0 +1 @@ +1502302578000010610834044101581512311545562525 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/crash1.bin b/vendor/github.com/klauspost/compress/testdata/crash1.bin new file mode 100644 index 0000000000000000000000000000000000000000..d483846c4b82d579d8b101505ad6369cfb8a0350 GIT binary patch literal 5 Mcmey*!0`1S00-y-^8f$< literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/testdata/crash2.bin b/vendor/github.com/klauspost/compress/testdata/crash2.bin new file mode 100644 index 0000000..721a653 --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/crash2.bin @@ -0,0 +1 @@ +313254615470505 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/crash3.bin b/vendor/github.com/klauspost/compress/testdata/crash3.bin new file mode 100644 index 0000000..3e3d493 --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/crash3.bin @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/crash4.bin b/vendor/github.com/klauspost/compress/testdata/crash4.bin new file mode 100644 index 0000000..725b093 --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/crash4.bin @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/crash5.bin b/vendor/github.com/klauspost/compress/testdata/crash5.bin new file mode 100644 index 0000000..a521217 --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/crash5.bin @@ -0,0 +1 @@ +55511151231257827021181583404541015625 \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/dec-hang1.bin b/vendor/github.com/klauspost/compress/testdata/dec-hang1.bin new file mode 100644 index 0000000..e07926f --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/dec-hang1.bin @@ -0,0 +1 @@ +$ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/dec-hang2.bin b/vendor/github.com/klauspost/compress/testdata/dec-hang2.bin new file mode 100644 index 0000000..c1484ef --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/dec-hang2.bin @@ -0,0 +1 @@ +|CO \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/dec-hang3.bin b/vendor/github.com/klauspost/compress/testdata/dec-hang3.bin new file mode 100644 index 0000000..3bd97e9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/dec-hang3.bin @@ -0,0 +1 @@ +VV \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/dec-symlen1.bin b/vendor/github.com/klauspost/compress/testdata/dec-symlen1.bin new file mode 100644 index 0000000000000000000000000000000000000000..c5589c9936a51b7d209775e742b720718b7babae GIT binary patch literal 49 zcmWf6AS>|T|Nrd{3?_#@H0*HbRJbN!<2h-L(V_qQlUFSIR6q4U2;?vP3nW8B@?Qb~ DqDCG9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/testdata/endnonzero.bin b/vendor/github.com/klauspost/compress/testdata/endnonzero.bin new file mode 100644 index 0000000000000000000000000000000000000000..cf08368af172f6bd3e638e61dcdf2e3df4b57ddd GIT binary patch literal 7 LcmZQz009L604D$; literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/testdata/endzerobits.bin b/vendor/github.com/klauspost/compress/testdata/endzerobits.bin new file mode 100644 index 0000000000000000000000000000000000000000..d9952f921157dbd3c3b75af1e0b148070840fc1c GIT binary patch literal 5 McmZQzWME(f000UA0{{R3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/klauspost/compress/testdata/normcount2.bin b/vendor/github.com/klauspost/compress/testdata/normcount2.bin new file mode 100644 index 0000000..39050da --- /dev/null +++ b/vendor/github.com/klauspost/compress/testdata/normcount2.bin @@ -0,0 +1 @@ +868000113000000fd9F055125272181835410155551151-0_0040Y2BW4K_0x_j4L___e__331ms__QSlz_I__ \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/testdata/pngdata.bin b/vendor/github.com/klauspost/compress/testdata/pngdata.bin new file mode 100644 index 0000000000000000000000000000000000000000..f48a75c903d7190902665d0d817b72d53b3a0569 GIT binary patch literal 51200 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