spillgate 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. spillgate-0.1.0/.gitattributes +10 -0
  2. spillgate-0.1.0/.github/CODEOWNERS +1 -0
  3. spillgate-0.1.0/.github/dependabot.yml +8 -0
  4. spillgate-0.1.0/.github/workflows/ci.yml +72 -0
  5. spillgate-0.1.0/.github/workflows/codeql.yml +25 -0
  6. spillgate-0.1.0/.github/workflows/nightly-fuzz.yml +25 -0
  7. spillgate-0.1.0/.github/workflows/release.yml +61 -0
  8. spillgate-0.1.0/.github/workflows/scorecard.yml +27 -0
  9. spillgate-0.1.0/.gitignore +10 -0
  10. spillgate-0.1.0/CHANGELOG.md +13 -0
  11. spillgate-0.1.0/CONTRIBUTING.md +24 -0
  12. spillgate-0.1.0/LICENSE +21 -0
  13. spillgate-0.1.0/PKG-INFO +176 -0
  14. spillgate-0.1.0/README.md +126 -0
  15. spillgate-0.1.0/RELEASING.md +46 -0
  16. spillgate-0.1.0/SECURITY.md +31 -0
  17. spillgate-0.1.0/conformance/SCHEMA.md +94 -0
  18. spillgate-0.1.0/conformance/SOURCE +3 -0
  19. spillgate-0.1.0/conformance/manifest.json +11211 -0
  20. spillgate-0.1.0/conformance/manifest.schema.json +122 -0
  21. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0019.bin +0 -0
  22. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0020.bin +0 -0
  23. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0021.bin +0 -0
  24. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0022.bin +0 -0
  25. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0023.bin +0 -0
  26. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0024.bin +0 -0
  27. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0025.bin +0 -0
  28. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0026.bin +0 -0
  29. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0027.bin +0 -0
  30. spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0028.bin +0 -0
  31. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0010.bin +0 -0
  32. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0011.bin +0 -0
  33. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0012.bin +0 -0
  34. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0013.bin +0 -0
  35. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0014.bin +0 -0
  36. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0015.bin +0 -0
  37. spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0016.bin +0 -0
  38. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0001.bin +0 -0
  39. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0002.bin +0 -0
  40. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0003.bin +0 -0
  41. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0004.bin +0 -0
  42. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0005.bin +0 -0
  43. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0006.bin +0 -0
  44. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0007.bin +0 -0
  45. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0008.bin +0 -0
  46. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0009.bin +0 -0
  47. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0010.bin +0 -0
  48. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0011.bin +0 -0
  49. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0012.bin +0 -0
  50. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0013.bin +0 -0
  51. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0014.bin +0 -0
  52. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0015.bin +0 -0
  53. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0016.bin +0 -0
  54. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0017.bin +0 -0
  55. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0018.bin +0 -0
  56. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0019.bin +0 -0
  57. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0020.bin +0 -0
  58. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0021.bin +0 -0
  59. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0022.bin +0 -0
  60. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0023.bin +0 -0
  61. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0024.bin +0 -0
  62. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0025.bin +2 -0
  63. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0026.bin +2 -0
  64. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0027.bin +2 -0
  65. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0028.bin +2 -0
  66. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0029.bin +2 -0
  67. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0030.bin +0 -0
  68. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0031.bin +0 -0
  69. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0032.bin +0 -0
  70. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0033.bin +0 -0
  71. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0034.bin +0 -0
  72. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0035.bin +0 -0
  73. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0036.bin +0 -0
  74. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0037.bin +0 -0
  75. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0038.bin +0 -0
  76. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0039.bin +0 -0
  77. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0040.bin +0 -0
  78. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0041.bin +0 -0
  79. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0042.bin +0 -0
  80. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0043.bin +0 -0
  81. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0044.bin +0 -0
  82. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0045.bin +0 -0
  83. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0046.bin +0 -0
  84. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0047.bin +0 -0
  85. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0048.bin +0 -0
  86. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0049.bin +0 -0
  87. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0050.bin +0 -0
  88. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0051.bin +0 -0
  89. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0052.bin +0 -0
  90. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0053.bin +0 -0
  91. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0054.bin +0 -0
  92. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0055.bin +0 -0
  93. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0056.bin +0 -0
  94. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0057.bin +0 -0
  95. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0058.bin +0 -0
  96. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0059.bin +0 -0
  97. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0060.bin +0 -0
  98. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0061.bin +0 -0
  99. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0062.bin +0 -0
  100. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0063.bin +0 -0
  101. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0064.bin +0 -0
  102. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0065.bin +0 -0
  103. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0066.bin +0 -0
  104. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0067.bin +0 -0
  105. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0068.bin +0 -0
  106. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0069.bin +0 -0
  107. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0070.bin +0 -0
  108. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0071.bin +0 -0
  109. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0072.bin +0 -0
  110. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0073.bin +0 -0
  111. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0074.bin +0 -0
  112. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0075.bin +0 -0
  113. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0076.bin +0 -0
  114. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0077.bin +0 -0
  115. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0078.bin +0 -0
  116. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0079.bin +0 -0
  117. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0080.bin +0 -0
  118. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0081.bin +0 -0
  119. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0082.bin +0 -0
  120. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0083.bin +0 -0
  121. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0084.bin +0 -0
  122. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0085.bin +0 -0
  123. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0086.bin +0 -0
  124. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0087.bin +0 -0
  125. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0088.bin +0 -0
  126. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0089.bin +0 -0
  127. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0090.bin +0 -0
  128. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0091.bin +0 -0
  129. spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0092.bin +0 -0
  130. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0001.bin +0 -0
  131. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0002.bin +0 -0
  132. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0003.bin +1 -0
  133. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0004.bin +1 -0
  134. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0005.bin +0 -0
  135. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0006.bin +0 -0
  136. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0007.bin +0 -0
  137. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0008.bin +0 -0
  138. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0009.bin +0 -0
  139. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0010.bin +0 -0
  140. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0011.bin +0 -0
  141. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0012.bin +0 -0
  142. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0013.bin +0 -0
  143. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0014.bin +0 -0
  144. spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0015.bin +0 -0
  145. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0001.bin +0 -0
  146. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0002.bin +0 -0
  147. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0003.bin +0 -0
  148. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0004.bin +0 -0
  149. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0005.bin +0 -0
  150. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0006.bin +0 -0
  151. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0007.bin +0 -0
  152. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0008.bin +0 -0
  153. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0009.bin +0 -0
  154. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0010.bin +0 -0
  155. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0011.bin +0 -0
  156. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0012.bin +0 -0
  157. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0013.bin +0 -0
  158. spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0014.bin +0 -0
  159. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0001.bin +0 -0
  160. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0002.bin +0 -0
  161. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0003.bin +0 -0
  162. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0004.bin +0 -0
  163. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0005.bin +0 -0
  164. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0006.bin +0 -0
  165. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0007.bin +0 -0
  166. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0008.bin +0 -0
  167. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0009.bin +0 -0
  168. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0010.bin +0 -0
  169. spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0011.bin +0 -0
  170. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0001.bin +0 -0
  171. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0002.bin +1 -0
  172. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0003.bin +1 -0
  173. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0004.bin +1 -0
  174. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0005.bin +0 -0
  175. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0006.bin +0 -0
  176. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0007.bin +0 -0
  177. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0008.bin +0 -0
  178. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0009.bin +0 -0
  179. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0010.bin +0 -0
  180. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0011.bin +0 -0
  181. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0012.bin +0 -0
  182. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0013.bin +0 -0
  183. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0014.bin +0 -0
  184. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0015.bin +0 -0
  185. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0016.bin +0 -0
  186. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0017.bin +0 -0
  187. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0018.bin +0 -0
  188. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0019.bin +0 -0
  189. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0020.bin +0 -0
  190. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0021.bin +0 -0
  191. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0022.bin +0 -0
  192. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0023.bin +0 -0
  193. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0024.bin +0 -0
  194. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0025.bin +0 -0
  195. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0026.bin +0 -0
  196. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0027.bin +0 -0
  197. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0028.bin +0 -0
  198. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0029.bin +0 -0
  199. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0030.bin +0 -0
  200. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0031.bin +0 -0
  201. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0032.bin +0 -0
  202. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0033.bin +0 -0
  203. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0034.bin +0 -0
  204. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0035.bin +0 -0
  205. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0036.bin +0 -0
  206. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0037.bin +0 -0
  207. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0038.bin +0 -0
  208. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0039.bin +0 -0
  209. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0040.bin +0 -0
  210. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0041.bin +1 -0
  211. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0042.bin +0 -0
  212. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0043.bin +0 -0
  213. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0044.bin +1 -0
  214. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0045.bin +1 -0
  215. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0046.bin +1 -0
  216. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0047.bin +0 -0
  217. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0048.bin +0 -0
  218. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0049.bin +0 -0
  219. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0050.bin +0 -0
  220. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0051.bin +0 -0
  221. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0052.bin +0 -0
  222. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0053.bin +0 -0
  223. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0054.bin +0 -0
  224. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0055.bin +0 -0
  225. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0056.bin +0 -0
  226. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0057.bin +0 -0
  227. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0058.bin +0 -0
  228. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0059.bin +0 -0
  229. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0060.bin +0 -0
  230. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0061.bin +0 -0
  231. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0062.bin +0 -0
  232. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0063.bin +0 -0
  233. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0064.bin +0 -0
  234. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0065.bin +1 -0
  235. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0066.bin +1 -0
  236. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0067.bin +0 -0
  237. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0068.bin +0 -0
  238. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0069.bin +0 -0
  239. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0070.bin +0 -0
  240. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0071.bin +0 -0
  241. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0072.bin +0 -0
  242. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0073.bin +1 -0
  243. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0074.bin +1 -0
  244. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0075.bin +1 -0
  245. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0076.bin +0 -0
  246. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0077.bin +0 -0
  247. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0078.bin +0 -0
  248. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0079.bin +0 -0
  249. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0080.bin +0 -0
  250. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0081.bin +0 -0
  251. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0082.bin +0 -0
  252. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0083.bin +0 -0
  253. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0084.bin +0 -0
  254. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0085.bin +0 -0
  255. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0086.bin +1 -0
  256. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0087.bin +1 -0
  257. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0088.bin +1 -0
  258. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0089.bin +0 -0
  259. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0090.bin +0 -0
  260. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0091.bin +0 -0
  261. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0092.bin +0 -0
  262. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0093.bin +0 -0
  263. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0094.bin +0 -0
  264. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0095.bin +0 -0
  265. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0096.bin +0 -0
  266. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0097.bin +0 -0
  267. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0098.bin +0 -0
  268. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0099.bin +1 -0
  269. spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0100.bin +0 -0
  270. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0001.bin +0 -0
  271. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0002.bin +0 -0
  272. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0003.bin +0 -0
  273. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0004.bin +0 -0
  274. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0005.bin +0 -0
  275. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0006.bin +0 -0
  276. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0007.bin +0 -0
  277. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0008.bin +0 -0
  278. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0009.bin +0 -0
  279. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0010.bin +0 -0
  280. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0011.bin +0 -0
  281. spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0012.bin +0 -0
  282. spillgate-0.1.0/conformance/vectors/small/SG-V-RAT-0001.bin +0 -0
  283. spillgate-0.1.0/conformance/vectors/small/SG-V-RAT-0009.bin +0 -0
  284. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0010.bin +0 -0
  285. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0011.bin +0 -0
  286. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0012.bin +0 -0
  287. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0013.bin +0 -0
  288. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0014.bin +0 -0
  289. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0015.bin +0 -0
  290. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0016.bin +0 -0
  291. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0017.bin +0 -0
  292. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0018.bin +0 -0
  293. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0019.bin +0 -0
  294. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0020.bin +0 -0
  295. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0021.bin +0 -0
  296. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0022.bin +0 -0
  297. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0023.bin +0 -0
  298. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0024.bin +0 -0
  299. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0025.bin +0 -0
  300. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0026.bin +0 -0
  301. spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0027.bin +0 -0
  302. spillgate-0.1.0/docs/how-to.md +443 -0
  303. spillgate-0.1.0/docs/memory.md +29 -0
  304. spillgate-0.1.0/pyproject.toml +58 -0
  305. spillgate-0.1.0/spec/SPEC.md +153 -0
  306. spillgate-0.1.0/spec/generators.md +49 -0
  307. spillgate-0.1.0/src/spillgate/__init__.py +77 -0
  308. spillgate-0.1.0/src/spillgate/_cancel.py +25 -0
  309. spillgate-0.1.0/src/spillgate/_chain.py +117 -0
  310. spillgate-0.1.0/src/spillgate/_deflate.py +89 -0
  311. spillgate-0.1.0/src/spillgate/_guard.py +154 -0
  312. spillgate-0.1.0/src/spillgate/_gzip.py +128 -0
  313. spillgate-0.1.0/src/spillgate/_inflate.py +71 -0
  314. spillgate-0.1.0/src/spillgate/_meter.py +204 -0
  315. spillgate-0.1.0/src/spillgate/br.py +203 -0
  316. spillgate-0.1.0/src/spillgate/codec.py +44 -0
  317. spillgate-0.1.0/src/spillgate/decoder.py +201 -0
  318. spillgate-0.1.0/src/spillgate/errors.py +224 -0
  319. spillgate-0.1.0/src/spillgate/header.py +106 -0
  320. spillgate-0.1.0/src/spillgate/limits.py +141 -0
  321. spillgate-0.1.0/src/spillgate/py.typed +0 -0
  322. spillgate-0.1.0/src/spillgate/zstd.py +275 -0
  323. spillgate-0.1.0/tests/corpus.py +408 -0
  324. spillgate-0.1.0/tests/helpers.py +74 -0
  325. spillgate-0.1.0/tests/test_api_contract.py +131 -0
  326. spillgate-0.1.0/tests/test_br.py +212 -0
  327. spillgate-0.1.0/tests/test_codecs.py +270 -0
  328. spillgate-0.1.0/tests/test_conformance.py +273 -0
  329. spillgate-0.1.0/tests/test_hardening.py +300 -0
  330. spillgate-0.1.0/tests/test_limits_and_header.py +305 -0
  331. spillgate-0.1.0/tests/test_properties.py +158 -0
  332. spillgate-0.1.0/tests/test_python_traps.py +203 -0
  333. spillgate-0.1.0/tests/test_reader_contract.py +462 -0
  334. spillgate-0.1.0/tests/test_review_codecs.py +60 -0
  335. spillgate-0.1.0/tests/test_review_fresh.py +56 -0
  336. spillgate-0.1.0/tests/test_zstd.py +308 -0
  337. spillgate-0.1.0/tools/spectrace.py +66 -0
@@ -0,0 +1,10 @@
1
+ # Text is LF everywhere so hashes and golden files are identical on every OS.
2
+ * text=auto eol=lf
3
+
4
+ # Conformance vectors are byte-exact; never normalize them.
5
+ conformance/vectors/** -text
6
+ *.gz -text
7
+ *.zz -text
8
+ *.br -text
9
+ *.zst -text
10
+ *.bin -text
@@ -0,0 +1 @@
1
+ * @FelixMiddelhoff
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule: { interval: weekly }
6
+ - package-ecosystem: pip
7
+ directory: /
8
+ schedule: { interval: weekly }
@@ -0,0 +1,72 @@
1
+ name: ci
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: ci-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ test:
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest, windows-latest]
21
+ python: ["3.11", "3.12", "3.13", "3.14"]
22
+ runs-on: ${{ matrix.os }}
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ with: { persist-credentials: false }
26
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
27
+ with: { python-version: "${{ matrix.python }}" }
28
+ - run: python -m pip install pytest hypothesis "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
29
+ - name: tests (all 354 conformance vectors with brotli and zstd, properties, traps)
30
+ run: python -m pytest
31
+ env:
32
+ SPILLGATE_NO_SKIPS: "1" # a missing codec fails the run instead of skipping vectors
33
+ core-only:
34
+ # The core must work and test cleanly without any optional dependency.
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
38
+ with: { persist-credentials: false }
39
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
40
+ with: { python-version: "3.11" }
41
+ - run: python -m pip install pytest hypothesis
42
+ - run: python -m pytest -m "not large"
43
+ audit:
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
47
+ with: { persist-credentials: false }
48
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
49
+ with: { python-version: "3.13" }
50
+ - run: python -m pip install pip-audit "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
51
+ - name: known vulnerabilities in the optional dependencies
52
+ run: python -m pip_audit
53
+
54
+ static:
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
58
+ with: { persist-credentials: false }
59
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
60
+ with: { python-version: "3.13" }
61
+ - run: python -m pip install ruff mypy pytest hypothesis build brotli zstandard
62
+ - run: python -m ruff check .
63
+ - run: python -m ruff format --check .
64
+ - run: python -m mypy
65
+ - name: every rule of the specification is covered
66
+ run: python tools/spectrace.py
67
+ - name: the package builds and installs into a clean environment
68
+ run: |
69
+ python -m build
70
+ python -m venv /tmp/clean
71
+ /tmp/clean/bin/python -m pip install dist/*.whl
72
+ /tmp/clean/bin/python -I -c "import spillgate; print(spillgate.Limits(max_output=1))"
@@ -0,0 +1,25 @@
1
+ name: codeql
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ pull_request:
6
+ push:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "41 3 * * 1"
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ analyze:
16
+ runs-on: ubuntu-latest
17
+ permissions:
18
+ contents: read
19
+ security-events: write
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with: { persist-credentials: false }
23
+ - uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
24
+ with: { languages: python, build-mode: none }
25
+ - uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
@@ -0,0 +1,25 @@
1
+ name: nightly-fuzz
2
+
3
+ # Property tests with a much larger example budget than the pull-request run.
4
+ on:
5
+ schedule:
6
+ - cron: "27 2 * * *"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ hypothesis:
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 90
16
+ steps:
17
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
18
+ with: { persist-credentials: false }
19
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
20
+ with: { python-version: "3.13" }
21
+ - run: python -m pip install pytest hypothesis
22
+ - name: properties with a large budget
23
+ run: python -m pytest tests/test_properties.py
24
+ env:
25
+ SPILLGATE_HYPOTHESIS_EXAMPLES: "200000"
@@ -0,0 +1,61 @@
1
+ name: release
2
+
3
+ # Publishes to PyPI with Trusted Publishing (OpenID Connect): no API token is stored anywhere.
4
+ # It runs only for a tag like v0.1.0 that the maintainer pushes, builds exactly once, checks
5
+ # that the tag equals the package version, tests the built wheel in a clean environment and
6
+ # then publishes the same files from a protected environment.
7
+ on:
8
+ push:
9
+ tags: ["v[0-9]+.[0-9]+.[0-9]+"]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19
+ with: { persist-credentials: false }
20
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
21
+ with: { python-version: "3.13" }
22
+ - run: python -m pip install build twine pytest hypothesis "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
23
+ - name: the tag must equal the package version
24
+ run: |
25
+ version=$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
26
+ test "v$version" = "$GITHUB_REF_NAME" || { echo "tag $GITHUB_REF_NAME != version $version"; exit 1; }
27
+ - name: the full suite passes, nothing skipped
28
+ run: python -m pytest
29
+ env:
30
+ SPILLGATE_NO_SKIPS: "1"
31
+ - run: python -m build
32
+ - run: python -m twine check --strict dist/*
33
+ - name: the wheel works in a clean environment
34
+ run: |
35
+ python -m venv /tmp/clean
36
+ /tmp/clean/bin/python -m pip install dist/*.whl
37
+ /tmp/clean/bin/python -I -c "import spillgate; print(spillgate.Limits(max_output=1))"
38
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
39
+ with:
40
+ name: dist
41
+ path: dist/
42
+ if-no-files-found: error
43
+
44
+ publish:
45
+ needs: build
46
+ runs-on: ubuntu-latest
47
+ # The environment "pypi" is created in the repository settings and requires the maintainer's
48
+ # approval before this job runs. The PyPI project trusts exactly this workflow and
49
+ # environment (see RELEASING.md).
50
+ environment:
51
+ name: pypi
52
+ url: https://pypi.org/p/spillgate
53
+ permissions:
54
+ id-token: write # the only permission that lets this job publish
55
+ steps:
56
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
57
+ with:
58
+ name: dist
59
+ path: dist/
60
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
61
+ # Attestations (build provenance) are produced by default and uploaded with the files.
@@ -0,0 +1,27 @@
1
+ name: scorecard
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches: [main]
7
+ schedule:
8
+ - cron: "23 4 * * 2"
9
+
10
+ permissions: read-all
11
+
12
+ jobs:
13
+ analysis:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ security-events: write
17
+ id-token: write
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ with: { persist-credentials: false }
21
+ - uses: ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e # v2.5.0
22
+ with:
23
+ results_file: results.sarif
24
+ results_format: sarif
25
+ publish_results: true
26
+ - uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
27
+ with: { sarif_file: results.sarif }
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ .hypothesis/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .venv/
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ Versions below 1.0 may still change the API.
4
+
5
+ ## 0.1.0 - 2026-11-11
6
+
7
+ First version. The Python implementation of the spillgate specification.
8
+
9
+ - `Limits` with a required `max_output`, ratio, layer, input limits; typed, sticky errors (one exception class per outcome kind).
10
+ - gzip, deflate and identity in the standard-library-only core; own gzip and zlib framing over `zlib.decompressobj` with `max_length` always greater than zero.
11
+ - Optional extras `spillgate[brotli]` (brotli >= 1.2.1) and `spillgate[zstd]` (zstandard >= 0.25.0) with window caps and bounded steps.
12
+ - Passes the full conformance corpus (354 vectors) of the reference implementation.
13
+ - Integration guide in `docs/how-to.md`.
@@ -0,0 +1,24 @@
1
+ # Contributing
2
+
3
+ ## Run the checks
4
+
5
+ ```
6
+ python -m pip install pytest hypothesis ruff mypy
7
+ python -m pytest # everything, including the large generated vectors (about 40 s)
8
+ python -m pytest -m "not large" # without the GiB-scale vectors
9
+ python tools/spectrace.py # every rule of the specification is named by a test or vector
10
+ SPILLGATE_NO_SKIPS=1 python -m pytest # with brotli and zstandard installed: no vector may be skipped
11
+ python -m ruff check . && python -m ruff format --check .
12
+ python -m mypy
13
+ ```
14
+
15
+ ## Rules
16
+
17
+ - The specification comes first. Behavior that the spec does not describe is not added here: change `spec/SPEC.md` in the reference repository, add vectors there, then sync.
18
+ - `spectrace` counts a rule as covered when a test docstring or a vector names it; that is a checklist, not proof that the test asserts everything the rule says. Review the assertions too.
19
+ - Test first for every bug. A test names the rules it protects in its docstring (`Covers: SG-R-...`); `tools/spectrace.py` reads that line.
20
+ - Never weaken a test or a conformance vector to make code pass.
21
+ - `conformance/` and `spec/` are copies. Do not edit them here; update them from the reference repository and record the release in `conformance/SOURCE`.
22
+ - The core has no dependencies and starts no threads. Optional codecs are extras.
23
+ - Never call an unbounded standard-library API (`zlib.decompress`, `gzip.decompress`, `GzipFile`, `decompress()` without `max_length`, `flush()`); `tests/test_python_traps.py` fails if the source does.
24
+ - Code is read by people: short functions, a docstring that explains why, rule IDs where a rule applies.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Felix Middelhoff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.5
2
+ Name: spillgate
3
+ Version: 0.1.0
4
+ Summary: Decode untrusted compressed data with mandatory limits (decompression-bomb gate).
5
+ Project-URL: Homepage, https://github.com/FelixMiddelhoff/spillgate-python
6
+ Project-URL: Specification, https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md
7
+ Author: Felix Middelhoff
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 Felix Middelhoff
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Keywords: brotli,content-encoding,decompression-bomb,deflate,gzip,security,zstd
31
+ Classifier: Development Status :: 4 - Beta
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3 :: Only
36
+ Classifier: Topic :: Security
37
+ Classifier: Topic :: System :: Archiving :: Compression
38
+ Classifier: Typing :: Typed
39
+ Requires-Python: >=3.11
40
+ Provides-Extra: brotli
41
+ Requires-Dist: brotli<2,>=1.2.1; extra == 'brotli'
42
+ Provides-Extra: dev
43
+ Requires-Dist: hypothesis>=6.100; extra == 'dev'
44
+ Requires-Dist: mypy>=1.11; extra == 'dev'
45
+ Requires-Dist: pytest>=8; extra == 'dev'
46
+ Requires-Dist: ruff>=0.6; extra == 'dev'
47
+ Provides-Extra: zstd
48
+ Requires-Dist: zstandard<1,>=0.25.0; extra == 'zstd'
49
+ Description-Content-Type: text/markdown
50
+
51
+ # spillgate (Python)
52
+
53
+ Decode untrusted compressed data in Python with mandatory limits. A decompression bomb
54
+ ends in a typed exception instead of exhausting memory.
55
+
56
+ ```python
57
+ from spillgate import Limits, OutputLimitError, decode_all
58
+
59
+ try:
60
+ body = decode_all(response_bytes, "gzip", Limits(max_output=8 * 2**20))
61
+ except OutputLimitError:
62
+ ... # refuse the response
63
+ ```
64
+
65
+ - `Content-Encoding` chains: `gzip` (and `x-gzip`), `deflate`, `identity`; `br` and `zstd` as
66
+ optional extras (see below).
67
+ - `max_output` is required. There is no unlimited setting.
68
+ - Every layer is limited, including the intermediate layers of a chain.
69
+ - Expansion ratio and chain length are limited by default.
70
+ - Unknown, malformed or too deep `Content-Encoding` headers are refused, never passed through.
71
+ - The core has no dependencies and starts no threads.
72
+
73
+ This is the Python implementation of the language-neutral
74
+ [spillgate specification](https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md).
75
+ It passes the same conformance corpus as the Go reference implementation.
76
+
77
+ Python 3.11 or newer. **Integrating it into your service: [docs/how-to.md](docs/how-to.md).**
78
+
79
+ ## Use
80
+
81
+ ```python
82
+ from spillgate import Decoder, Limits
83
+
84
+ decoder = Decoder(Limits(max_output=8 * 2**20)) # build once, share between threads
85
+
86
+ with decoder.reader(resp.raw, resp.headers.get_all("Content-Encoding", [])) as body:
87
+ for chunk in iter(lambda: body.read(65536), b""):
88
+ handle(chunk) # any exception: discard everything
89
+ ```
90
+
91
+ `decode_all` / `Decoder.read_all` return the whole body or raise, never partial data.
92
+ `Decoder.reader` streams; bytes can arrive before a later error, so treat any
93
+ `SpillgateError` as failure of the whole body.
94
+
95
+ `source` is `bytes` or any object with `read(n)`. It is not closed by spillgate.
96
+
97
+ ### Brotli and zstd
98
+
99
+ ```
100
+ pip install "spillgate[brotli]" # brotli >= 1.2.1
101
+ pip install "spillgate[zstd]" # zstandard >= 0.25.0
102
+ ```
103
+
104
+ ```python
105
+ from spillgate import Decoder, Limits, br, zstd
106
+
107
+ decoder = Decoder(
108
+ Limits(max_output=8 * 2**20),
109
+ codecs={"br": br.codec(), "zstd": zstd.codec()}, # offer only what you installed
110
+ )
111
+ ```
112
+
113
+ Both decoders are C libraries and are treated as untrusted: spillgate reads the window size
114
+ (brotli) or the whole frame structure (zstd) itself, refuses oversized windows as `memory_limit`
115
+ before anything is decoded, and gives the library bounded steps. The window costs memory per
116
+ request: up to 16 MiB for brotli and 8 MiB for zstd by default. Lower them with
117
+ `br.codec(max_window_bits=22)` and `zstd.codec(max_window_bytes=2**21)` when a server decodes
118
+ many requests at once. Older `brotli` versions are refused at import time: before 1.2.1 they
119
+ had no output limit and a memory-corruption bug in the decoder (CVE-2026-111497).
120
+ Always close readers (`with ... as body`) so the decoder state is released.
121
+
122
+ CPU: frames and blocks that produce no output cost CPU but neither output nor ratio limit sees
123
+ them. A zstd body made of millions of empty frames costs about one second per MB of input
124
+ (gzip: milliseconds). Bound the compressed size with `max_input` or your server's body limit.
125
+
126
+ ### Limits
127
+
128
+ | Field | Meaning | Default |
129
+ | --- | --- | --- |
130
+ | `max_output` | bytes one layer may produce, `1 .. 2**63-1` (required) | none |
131
+ | `max_layers` | longest chain, `1 .. 16` | 5 |
132
+ | `max_ratio` | output bytes per input byte the codec consumed | 1000 |
133
+ | `ratio_grace` | output below which the ratio is not checked | 64 KiB |
134
+ | `max_input` | cap on compressed bytes taken from the source | none |
135
+ | `disable_ratio_limit` | the one named opt-out of the ratio check | `False` |
136
+
137
+ `Limits` is immutable and validated when created. No number disables a limit: `0`, negative
138
+ values, floats, strings and `bool` are all refused with `InvalidLimitsError`.
139
+
140
+ ### Errors
141
+
142
+ Every refusal is a `SpillgateError` with a `kind` (`spillgate.Kind`), a `layer` and a
143
+ `limit`; there is one subclass per kind: `OutputLimitError`, `RatioLimitError`,
144
+ `LayerLimitError`, `InputLimitError`, `MemoryLimitError`, `UnsupportedEncodingError`,
145
+ `MalformedEncodingError`, `CorruptError`, `InternalError`, `CanceledError`, `SourceError`,
146
+ `InvalidLimitsError`. Errors are sticky: after one, every later read raises the same error.
147
+ Error messages never contain more than 32 bytes of attacker data, and that data is escaped.
148
+
149
+ `cancel=callable` on `reader` / `read_all` is polled before every read and every 4 KiB of
150
+ input. It cannot interrupt one step inside the decoder; the limits bound the work there.
151
+
152
+ ### Why not `zlib.decompress` or `gzip.GzipFile`?
153
+
154
+ Because they have no bound. The traps this library avoids: `decompressobj().decompress(data)`
155
+ without `max_length` (and `max_length=0`, which means *unlimited*), `flush()`, one-shot
156
+ `gzip.decompress`, and `GzipFile.read()` without a size. `tests/test_python_traps.py` scans the
157
+ source for them.
158
+
159
+ ## What it does not cover
160
+
161
+ Archives (zip, tar), bounding the compressed input (use `max_input` or limit the request body
162
+ size), connection timeouts, encrypted content, and memory-safety bugs in the C libraries
163
+ behind `zlib` and the optional codecs beyond what the limits contain. See
164
+ [docs/memory.md](docs/memory.md) for the memory bounds.
165
+
166
+ ## Specification and tests
167
+
168
+ `spec/SPEC.md` and `conformance/` are copies of the reference repository at the release named
169
+ in `conformance/SOURCE`. The suite runs all vectors (bombs, malformed streams, header attacks,
170
+ lying size fields), property tests, a scan for unbounded standard-library calls, and memory
171
+ measurements with `tracemalloc`. `python tools/spectrace.py` checks that every rule of the
172
+ specification is covered.
173
+
174
+ ## License
175
+
176
+ MIT, see [LICENSE](LICENSE). Report vulnerabilities as described in [SECURITY.md](SECURITY.md).
@@ -0,0 +1,126 @@
1
+ # spillgate (Python)
2
+
3
+ Decode untrusted compressed data in Python with mandatory limits. A decompression bomb
4
+ ends in a typed exception instead of exhausting memory.
5
+
6
+ ```python
7
+ from spillgate import Limits, OutputLimitError, decode_all
8
+
9
+ try:
10
+ body = decode_all(response_bytes, "gzip", Limits(max_output=8 * 2**20))
11
+ except OutputLimitError:
12
+ ... # refuse the response
13
+ ```
14
+
15
+ - `Content-Encoding` chains: `gzip` (and `x-gzip`), `deflate`, `identity`; `br` and `zstd` as
16
+ optional extras (see below).
17
+ - `max_output` is required. There is no unlimited setting.
18
+ - Every layer is limited, including the intermediate layers of a chain.
19
+ - Expansion ratio and chain length are limited by default.
20
+ - Unknown, malformed or too deep `Content-Encoding` headers are refused, never passed through.
21
+ - The core has no dependencies and starts no threads.
22
+
23
+ This is the Python implementation of the language-neutral
24
+ [spillgate specification](https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md).
25
+ It passes the same conformance corpus as the Go reference implementation.
26
+
27
+ Python 3.11 or newer. **Integrating it into your service: [docs/how-to.md](docs/how-to.md).**
28
+
29
+ ## Use
30
+
31
+ ```python
32
+ from spillgate import Decoder, Limits
33
+
34
+ decoder = Decoder(Limits(max_output=8 * 2**20)) # build once, share between threads
35
+
36
+ with decoder.reader(resp.raw, resp.headers.get_all("Content-Encoding", [])) as body:
37
+ for chunk in iter(lambda: body.read(65536), b""):
38
+ handle(chunk) # any exception: discard everything
39
+ ```
40
+
41
+ `decode_all` / `Decoder.read_all` return the whole body or raise, never partial data.
42
+ `Decoder.reader` streams; bytes can arrive before a later error, so treat any
43
+ `SpillgateError` as failure of the whole body.
44
+
45
+ `source` is `bytes` or any object with `read(n)`. It is not closed by spillgate.
46
+
47
+ ### Brotli and zstd
48
+
49
+ ```
50
+ pip install "spillgate[brotli]" # brotli >= 1.2.1
51
+ pip install "spillgate[zstd]" # zstandard >= 0.25.0
52
+ ```
53
+
54
+ ```python
55
+ from spillgate import Decoder, Limits, br, zstd
56
+
57
+ decoder = Decoder(
58
+ Limits(max_output=8 * 2**20),
59
+ codecs={"br": br.codec(), "zstd": zstd.codec()}, # offer only what you installed
60
+ )
61
+ ```
62
+
63
+ Both decoders are C libraries and are treated as untrusted: spillgate reads the window size
64
+ (brotli) or the whole frame structure (zstd) itself, refuses oversized windows as `memory_limit`
65
+ before anything is decoded, and gives the library bounded steps. The window costs memory per
66
+ request: up to 16 MiB for brotli and 8 MiB for zstd by default. Lower them with
67
+ `br.codec(max_window_bits=22)` and `zstd.codec(max_window_bytes=2**21)` when a server decodes
68
+ many requests at once. Older `brotli` versions are refused at import time: before 1.2.1 they
69
+ had no output limit and a memory-corruption bug in the decoder (CVE-2026-111497).
70
+ Always close readers (`with ... as body`) so the decoder state is released.
71
+
72
+ CPU: frames and blocks that produce no output cost CPU but neither output nor ratio limit sees
73
+ them. A zstd body made of millions of empty frames costs about one second per MB of input
74
+ (gzip: milliseconds). Bound the compressed size with `max_input` or your server's body limit.
75
+
76
+ ### Limits
77
+
78
+ | Field | Meaning | Default |
79
+ | --- | --- | --- |
80
+ | `max_output` | bytes one layer may produce, `1 .. 2**63-1` (required) | none |
81
+ | `max_layers` | longest chain, `1 .. 16` | 5 |
82
+ | `max_ratio` | output bytes per input byte the codec consumed | 1000 |
83
+ | `ratio_grace` | output below which the ratio is not checked | 64 KiB |
84
+ | `max_input` | cap on compressed bytes taken from the source | none |
85
+ | `disable_ratio_limit` | the one named opt-out of the ratio check | `False` |
86
+
87
+ `Limits` is immutable and validated when created. No number disables a limit: `0`, negative
88
+ values, floats, strings and `bool` are all refused with `InvalidLimitsError`.
89
+
90
+ ### Errors
91
+
92
+ Every refusal is a `SpillgateError` with a `kind` (`spillgate.Kind`), a `layer` and a
93
+ `limit`; there is one subclass per kind: `OutputLimitError`, `RatioLimitError`,
94
+ `LayerLimitError`, `InputLimitError`, `MemoryLimitError`, `UnsupportedEncodingError`,
95
+ `MalformedEncodingError`, `CorruptError`, `InternalError`, `CanceledError`, `SourceError`,
96
+ `InvalidLimitsError`. Errors are sticky: after one, every later read raises the same error.
97
+ Error messages never contain more than 32 bytes of attacker data, and that data is escaped.
98
+
99
+ `cancel=callable` on `reader` / `read_all` is polled before every read and every 4 KiB of
100
+ input. It cannot interrupt one step inside the decoder; the limits bound the work there.
101
+
102
+ ### Why not `zlib.decompress` or `gzip.GzipFile`?
103
+
104
+ Because they have no bound. The traps this library avoids: `decompressobj().decompress(data)`
105
+ without `max_length` (and `max_length=0`, which means *unlimited*), `flush()`, one-shot
106
+ `gzip.decompress`, and `GzipFile.read()` without a size. `tests/test_python_traps.py` scans the
107
+ source for them.
108
+
109
+ ## What it does not cover
110
+
111
+ Archives (zip, tar), bounding the compressed input (use `max_input` or limit the request body
112
+ size), connection timeouts, encrypted content, and memory-safety bugs in the C libraries
113
+ behind `zlib` and the optional codecs beyond what the limits contain. See
114
+ [docs/memory.md](docs/memory.md) for the memory bounds.
115
+
116
+ ## Specification and tests
117
+
118
+ `spec/SPEC.md` and `conformance/` are copies of the reference repository at the release named
119
+ in `conformance/SOURCE`. The suite runs all vectors (bombs, malformed streams, header attacks,
120
+ lying size fields), property tests, a scan for unbounded standard-library calls, and memory
121
+ measurements with `tracemalloc`. `python tools/spectrace.py` checks that every rule of the
122
+ specification is covered.
123
+
124
+ ## License
125
+
126
+ MIT, see [LICENSE](LICENSE). Report vulnerabilities as described in [SECURITY.md](SECURITY.md).
@@ -0,0 +1,46 @@
1
+ # Releasing to PyPI
2
+
3
+ Releases use PyPI **Trusted Publishing**: the workflow `.github/workflows/release.yml` proves its
4
+ identity to PyPI with a short-lived OpenID Connect token. No password or API token exists in the
5
+ repository, in GitHub secrets or on a developer machine.
6
+
7
+ ## One-time setup (maintainer)
8
+
9
+ 1. **GitHub environment.** Repository **Settings → Environments → New environment**, name `pypi`.
10
+ Add yourself under *Required reviewers* so that every publish needs an explicit approval.
11
+ Optionally restrict *Deployment branches and tags* to the pattern `v*`.
12
+ 2. **PyPI pending publisher.** On <https://pypi.org/manage/account/publishing/> add a *pending
13
+ publisher* (this creates the project name `spillgate` on the first publish):
14
+ - PyPI project name: `spillgate`
15
+ - Owner: `FelixMiddelhoff`
16
+ - Repository name: `spillgate-python`
17
+ - Workflow name: `release.yml`
18
+ - Environment name: `pypi`
19
+ 3. Turn on two-factor authentication for the PyPI account and keep the recovery codes safe.
20
+
21
+ The PyPI name is reserved only when the first release is published, so do step 2 and the first
22
+ release close together.
23
+
24
+ ## Each release
25
+
26
+ 1. Update `CHANGELOG.md` and set `version` in `pyproject.toml` (for example `0.1.0`). Commit to `main` and wait for a green CI.
27
+ 2. Tag exactly that version and push the tag:
28
+ ```
29
+ git tag -a v0.1.0 -m "v0.1.0"
30
+ git push origin v0.1.0
31
+ ```
32
+ 3. The `release` workflow builds once, checks that the tag equals the version, runs the whole suite
33
+ with brotli and zstd installed and nothing skipped, checks the wheel in a clean environment, and
34
+ waits for your approval in the `pypi` environment. After the approval it publishes the same
35
+ files, with build attestations, to PyPI.
36
+ 4. Check from a clean directory:
37
+ ```
38
+ python -m venv t && t/bin/python -m pip install "spillgate[brotli,zstd]==0.1.0"
39
+ ```
40
+ 5. Create the GitHub release from the tag with the changelog text.
41
+
42
+ ## Never
43
+
44
+ Never delete or move a published tag, and never re-upload a version: PyPI refuses it. A wrong
45
+ release is yanked on PyPI and fixed with the next patch version. Versions at or above 1.0 need
46
+ separate, explicit consent.